关于java:微信为什么使用-SQLite-保存聊天记录来长长见识了

42次阅读

共计 3999 个字符,预计需要花费 10 分钟才能阅读完成。

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. 布尔字面量和判断
  2. 窗口函数
  3. Filter 子句
  4. Insert … on conflict (“Upsert”)
  5. 重命名列
  6. 在 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 target
SELECT *
  FROM source
    ON CONFLICT (id)
    DO UPDATE SET val = excluded.val

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

INSERT INTO target
SELECT *
  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:据我所知,兴许能够通过可更新视图或派生的列来模仿该性能。

原文:https://modern-sql.com/blog/2…

近期热文举荐:

1.1,000+ 道 Java 面试题及答案整顿 (2022 最新版)

2. 劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4. 别再写满屏的爆爆爆炸类了,试试装璜器模式,这才是优雅的形式!!

5.《Java 开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞 + 转发哦!

正文完
 0