news 2026/7/1 19:21:11

SQLite处理随机数据慢?预排序让插入性能提升2 - 3倍!

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SQLite处理随机数据慢?预排序让插入性能提升2 - 3倍!

随机数据的挑战

2026年6月7日,安德斯·墨菲探讨了SQLite性能优化问题。在上一篇文章中,探讨了 UUID4的随机性如何对插入速度产生重大影响,以及UUID7如何解决这一问题。但当面对其他具有随机特性的数据,而UUID7又无法解决问题时,该怎么办呢?将使用由 `SecureRandom` 生成的160位(20字节)随机值,类似 这篇文章 中描述的情况。对于会话令牌这类数据,可能不想使用UUID7,因为它会泄露信息,且可能无法满足用例对熵的要求等。这也代表任何主键为随机(更确切说是无序)的数据。

以下是生成这些随机值的代码:

(defn **random-unguessable-uid** []
(let [buffer (byte-array 20)]
(.nextBytes secure-random buffer)))

来看看它的性能表现:

(d/q writer
["CREATE TABLE IF NOT EXISTS event(id BLOB PRIMARY KEY, data BLOB) WITHOUT ROWID"])

(dotimes [_ 10]
(time
(d/with-write-tx [db writer]
(dotimes [_ 1000000]
(d/q db ["INSERT INTO event (id, data) values (?, ?)"
(random-unguessable-id) data])))))

结果如下:

总行数时间(毫秒)
10000002478
20000004927
30000006262
40000007195
50000008257
60000008704
70000009244
80000009771
900000010387
1000000011103

每秒大约插入十万条记录,和使用UUID4一样,插入速度很慢。

预排序的解决方案

B+树的显著特点是有序,顺序写入速度很快。而随机数据会破坏这一特性,导致页面频繁刷新、页面分裂和树的重新平衡,影响性能。不过,数据已进行了批量处理。那么,在插入数据之前对其进行排序会怎样呢?

首先,需要一种快速比较随机ID的方法。这些ID是20字节的,不想逐个字节进行比较,所以只取前8个字节并将其转换为长整型。在大多数情况下,不需要比较整个字节数组就能实现较好的排序效果。重要的是,这种比较是无符号的,以与SQLite保持一致。

当比较两个BLOB值时,结果由 `memcmp()` 函数决定。

注意:这可能不是对随机数据进行排序的最快方法。写博客时通常不联网(联网太容易分心),而且现在的搜索功能也不太好用。所以主要依靠离线文档,使用 Dash(Linux下的等效工具是Zeal)进行模糊文本搜索。如果知道在Java/Clojure中更快更好的字节数组排序方法,请告知!

以下是相关代码:

(defn **bytes->long** [^bytes bytes]
(-> (ByteBuffer/wrap bytes 0 8)
(ByteBuffer/.getLong 0)))

(defn **byte-compare**
"比较字节数组的前8个最高有效字节。
大端字节序(与SQLite的BLOB排序一致)。"
[a b]
(Long/compareUnsigned
(bytes->long a)
(bytes->long b)))

看看排序后的性能表现:

(d/q writer
["CREATE TABLE IF NOT EXISTS event(id BLOB PRIMARY KEY, data BLOB) WITHOUT ROWID"])

(dotimes [_ 10]
(time
(d/with-write-tx [db writer]
(->> (repeatedly 1000000 random-unguessable-id)
(sort byte-compare)
(run! (fn [id]
(d/q db ["INSERT INTO event (it, data) values (?, ?)" id data])))))))

结果如下:

总行数时间(毫秒)
10000001987
20000002251
30000002296
40000002614
50000002687
60000003244
70000003118
80000003311
90000003485
100000003835

很有趣!尽管排序会带来一些开销,但对批量数据进行排序可以将性能提升约2 - 3倍。

结论

希望这篇文章能让大家了解到,在处理无序数据时,对数据进行批量处理并采用预排序等优化方法的好处。完整的基准测试代码可以在 这里 找到。

感谢 Datastar Discord 上阅读本文草稿并提供反馈的每一个人。

讨论

  • Hacker News
  • Reddit
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/1 19:20:45

零基础小白也能上手:AI建站工具极速操作步骤拆解

不写代码、不学设计,真的能自己建站吗 完全可以。这不再是口号,而是当下AI建站工具普及后的事实。很多对技术一窍不通的小白,包括实体店老板、手工艺人、刚入行的运营,都已经用AI搭建了自己的第一个网站。 这篇文章不跟你讲复杂的…

作者头像 李华
网站建设 2026/7/1 19:17:57

迅尔涡街流量计解析:适合需宽量程比蒸汽计量的工业用户

涡街流量计:蒸汽计量的主流技术选择 在进行高精度蒸汽计量用什么类型的流量计比较好这一问题的选型时,涡街流量计通常是工业现场的主流选项。相较于孔板、喷嘴等传统节流式流量计,涡街流量计依据卡门旋涡原理工作,无需差压变送器…

作者头像 李华
网站建设 2026/7/1 19:14:35

2026年,这家口碑不错的复合材料设备机构究竟有何独特魅力?

在复合材料设备领域,随着行业的不断发展,诸多技术挑战也逐渐凸显。当前,复合材料设备领域面临着传统设备智能化不足、生产工艺零散、环保性差、适配性低等问题。数据表明,多数传统老旧产线依赖人工操作,生产节奏慢&…

作者头像 李华
网站建设 2026/7/1 19:09:16

从SQL注入到XSS与文件包含:熊海CMS靶场实战与Web安全思维拓展

1. 项目概述:从SQL注入到更广阔的漏洞视野在网络安全学习和渗透测试的入门阶段,SQL注入往往是大家接触的第一个“重量级”漏洞。它逻辑直观,利用方式多样,从联合查询到报错注入、盲注,每一步都充满了挑战与成就感。因此…

作者头像 李华