SQLite 是一个被大家低估的数据库,但有些人认为它是一个不适宜生产环境应用的玩具数据库。事实上,SQLite 是一个十分牢靠的数据库,它能够解决 TB 级的数据,但它没有网络层。接下来,本文将与大家独特探讨 SQLite 在过来一年中最新的 SQL 性能。

SQLite “只是”一个库,它不是传统意义上的服务器。因而,在某些场合下,它的确不适合。然而,在相当多的其余场合,它却是最合适的抉择。SQLite 号称是部署和应用最宽泛的数据库引擎。我认为这很有可能,因为 SQLite 没有版权的限度。无论何时,只有开发者想应用 SQL 在文件中存储结构化的数据,SQLite 应是首选计划。

SQLite 的 SQL 方言也十分弱小。它比 MySQL 早四年就开始反对 with 语句。最近,它还实现了对于窗口函数的反对,这仅仅比 MySQL 晚五个月。

接下来,本文将介绍 SQLite 在 2018 年新减少的 SQL 性能,也就是 SQLite 从版本 3.22.0 到 3.26.0 所新减少的 SQL 性能。

具体内容包含:

    1. 布尔字面量和判断
    1. 窗口函数
    1. Filter子句
    1. Insert … on conflict (“Upsert”)
    1. 重命名列
    1. 在Modern-SQL.com上接下来

布尔变量和判断

SQLite反对“假”布尔值:它承受Boolean作为类型的名称,但它将其当作整数对待(这一点十分相似于MySQL)。真值true和false别离由数值1和0示意(这一点和C语言一样)。

从版本3.23.0开始,SQLite将关键字true和false别离用数字1和0示意,并反对is [not] true | false的判断语句。当初,它不再反对关键字unknown。开发者能够应用空值null来代替,因为unknown和null的布尔值是一样的。

在INSERT和UPDATE语句中,字面量true和false能够大大提高values和set子句的可读性。

is [not] true | false这个判断语句很有用,它与比拟操作的含意不一样:

咱们来比拟一下

WHERE c <> FALSE 

WHERE c IS NOT FALSE

在下面的例子中,如果c是null, 那么c <> false的后果是unknown.

这是因为WHERE子句只承受后果为true的值,它会过滤掉后果为false或unknown的值。这样,它就会把对应的行从后果中去掉。

与此绝对应,如果c是null,那么,c is not false的判断后果是true。因而,第二个WHERE子句也将蕴含c是null的行。

要达到同样的成果,您能够采纳的另外一种办法是减少独自解决null值的子句。也就是应用语句:

WHERE c <> FALSE   OR c IS NULL

这种模式的语句更长并且有一些冗余语句(c被应用了两次)。长话短说,能够应用is not false判断来代替这个or…is-null的语句。更具体的内容,请参考“Binary Decisions Based on Three-Valued Results”。

SQLite中对布尔字面量和布尔判断的反对当初和其余开源数据库靠近,惟一的差距是SQLite不反对is[not] unknown(你能够应用is [not] null来代替)。乏味的是,这些性能在上面提到的商用产品中还不可用。

0:只反对true,false.不反对notknown,如果须要,用null代替1:不反对is [not] unknown,如果须要,用is [not] null代替

窗口函数

SQLite 3.25.0引入了窗口函数。如果你晓得窗口函数,那么也晓得这是一件小事。如果你不理解窗口性能,请你本人学习如何应用。这篇文章不会具体解释窗口函数,但请置信:它是最重要的“古代”SQL个性。

SQLite对over子句的反对与其余数据库十分靠近。惟一值得注意的限度是range语句不反对数字或距离间隔(仅反对current row和unbounded preceding|following)。在公布sqlite 3.25.0时,SQL Server和PostgreSQL具备同样的限度。PostgreSQL 11打消了这一限度。

0:没有变动
1:Range范畴定义不反对datetime类型
2:Range范畴不承受关键字 (只反对unbounded和current row)

SQLite对于窗口函数的反对在业界是当先的。它不反对的性能在其余一些次要产品中也同样不反对(在聚合中语句中的distinct,width_bucket, respect|ignore nulls和from first|last等语句)。

0:同样没有ORDER BY 语句
1:不容许负偏移量,nulls的特定解决:lead(, 'IGNORE NULLS'),这里是字符串参数
2:没有缺省值(第三个参数),不反对respect|ignore nulls语句
3:不容许负偏移量,不反对ignore nulls语句
4:不容许负偏移量
5:不反对respect|ignore nulls语句
6:不容许负偏移量,不反对respect|ignore nulls语句
7:nulls的特定解决:first_value(, 1, null, 'IGNORE NULLS') ,这里是字符串参数。
8:不反对ignore nulls语句9:不反对ignore nulls语句和from last语句

过滤语句

尽管filter语句只是语法糖——你也能够很容易地应用表达式来取得雷同的后果——我认为它也是必不可少的语法糖,因为它能使人们更加容易地学习和了解SQL语句。

看看上面的select子句,您感觉哪一个更容易了解?

SELECT SUM(revenue) total_revenue     , SUM(CASE WHEN product = 1                 THEN revenue            END          ) prod1_revenue   ...

SELECT SUM(revenue) total_revenue     , SUM(revenue) FILTER(WHERE product = 1) prod1_revenue   ...

此示例很好地总结了filter子句的作用:它是聚合函数的后缀,能够在进行聚合之前依据特定条件,过滤掉相应的行。pivot技术是filter子句最常见的用例。这包含将实体属性值(EAV)模型中的属性转换为表格的列,如果想理解更多的内容,能够参考链接“filter-Selective Aggregates”(https://modern-sql.com/featur...)。

SQLite 从版本3.25.0开始,在应用over子句的聚合函数中反对了filter子句,然而在应用group by子句的聚合函数中还不反对。可怜的是,这意味着您依然无奈在SQLite中应用filter语句来解决上述情况。你必须像以前一样应用case表达式。我真的心愿SQLite在这一点上能尽快做到。

Insert … on conflict (“Upsert”)

SQLite 从版本3.24.0开始,引入了“upsert”概念:它是一个insert语句,能够优雅地解决主键和惟一束缚的抵触。您能够抉择疏忽这些抵触(在on conflict语句中什么都不做)或者更新以后行(在on conflict语句中执行更新操作)。

这是一个特有的SQL扩大,即它不是规范SQL的一部分,因而在上面的矩阵中是灰色的。然而,SQLite恪守与PostgreSQL雷同的语法来实现此性能0。该规范提供了对merge语句的反对。

与PostgreSQL不同,SQLite在以下语句中存在问题。

INSERT INTO targetSELECT *  FROM source    ON CONFLICT (id)    DO UPDATE SET val = excluded.val

依据阐明文档,这是因为解析器无奈判断关键字ON是SELECT语句的连贯束缚还是upsert子句的结尾。你能够通过向查问中增加子句来解决,例如where true。

INSERT INTO targetSELECT *  FROM source WHERE true    ON CONFLICT (id)    DO UPDATE SET val = excluded.val

0:同样记录insert、update、delete和merge操作的错误信息 (“DML error logging”)

1:On conflict语句不能紧挨查问的from语句,如果须要,能够增加  where true语句来分隔。

重命名列

SQLite引入的另一个特有性能是重命名基准数据库表中的列1。规范的SQL不反对此类性能2。

SQLite遵循其余产品罕用的语法来重命名列:

ALTER TABLE … RENAME COLUMN … TO

0:请查阅 sp_rename.

其余音讯

在2018年,SQLite除了在SQL语法上的变动,还有一些利用程序接口(API)的变动。你能够查阅sqlite.com(https://www.sqlite.org/news.html)上的新闻局部来理解更具体的音讯。

脚标:

  • 0:SQLite通常遵循PostgreSQL语法,Richard Hipp将此称为PostgreSQL会怎么做(WWPD)。
  • 1:基准数据库表是指用Create table语句创立的数据库表。派生的数据库表(如Select语句返回的查问后果集)中的列名能够通过SELECT语句、FROM语句或WITH语句来进行扭转
  • 2:据我所知,兴许能够通过可更新视图或派生的列来模仿该性能。