首页 时政热点 科技头条 智能AI 安全攻防 数码硬件 开发者生态 汽车 游戏 社会热点 开源推荐 医疗健康 归档 标签 关于

为什么 DuckDB 2.0 更快

摘要

VARIANT: smaller and faster than JSON Everybody loves JSON. VARIANT is now a first-class data type in DuckDB, and the word to remember is shredding. Not the guitar kind. Shredding in our VARIANT conte...

type user country amount the purchase and JSON VARIANT DuckDB
2026-10-11 1 阅读 约10分钟阅读 tosh
分享:
字号:
VARIANT:比 JSON 更小、更快 每个人都喜欢 JSON。 VARIANT 现在是 DuckDB 中的一流数据类型,要记住的词是粉碎。不是吉他那种。在我们的 VARIANT 上下文中分解意味着:当 DuckDB 将行组写入磁盘时,它会查看您的 JSON 列并查找每次在大多数行中显示的具有相同类型值的字段。这是一个常见的示例,五百万个事件中的一个: { "type" : "purchase" , "user" : { "id" : 42 , "country" : "FR" , "premium" : true }, "props" : { "amount" : 12.5 , "currency" : "EUR" , "items" : 2 }, "tags" : [ "a" , "b" ]} 事件类型始终为文本,user.id 始终为数字,props.amount 始终为小数。这些字段在引擎盖下被拉出到它们自己的真实列中。稀有字段以及一行为数字、下一行为文本的字段以二进制余数形式保留在一起。因此,JSON 的一致部分会像普通表一样存储,只有混乱的部分会存储为 blob。 JSON 与 VARIANT SELECT count (*) FROM ev WHERE type = 'purchase' AND user.country = 'FR' ; DuckDB 1.5.5 JSON 字符串,在查询时负载解析 · 存储为文本 {"type":"click", "user":{"id":51054,"country":"BR"},"amount":null} {"type":"click", "user":{"id":51054,"country":"BR"},"amount":null} {"type":"purchase", "user":{"id":42,"country":"FR"},"amount":12.5} {"type":"购买", "user":{"id":42,"country":"FR"},"amount":12.5} {"type":"view", "user":{"id":11,"country":"FR"},"amount":null} {"type":"view", "user":{"id":11,"country":"FR"},"amount":null} {"type":"购买", "user":{"id":8890,"country":"US"},"amount":301.2} {"type":"购买", "user":{"id":8890,"country":"US"},"amount":301.2} type · 解析后国家 · 解析后点击 BR 购买 FR 查看 FR 购买 US 字符读取 0 18 32 43 51 57 61 63 64 65 74 90 103 112 119 124 127 129 130 147 160 170 178 183 187 189 191 201 217 230 240 248 253 256 258 259 DuckDB 2.0 alpha VARIANT,在检查点负载处粉碎 · 存储为 VARIANT {"type":"click", "user":{"id":51054,"country":"BR"},"amount":null} {"type":"click", "user":{"id":51054,"country":"BR"},"amount":null} {"type":"购买", "user":{"id":42,"country":"FR"},"amount":12.5} {"type":"购买", "user":{"id":42,"country":"FR"},"amount":12.5} {"type":"view", "user":{"id":11,"country":"FR"},"amount":null} {"type":"view", "user":{"id":11,"country":"FR"},"amount":null} {"type":"purchase", "user":{"id":8890,"country":"US"},"amount":301.2} {"type":"purchase", "user":{"id":8890,"country":"US"},"amount":301.2} type user.id Country amount click 51054 BR null buy 42 FR 12.5 view 11 FR null 购买 8890 US 301.2 读取值 0 2 4 6 8 完美的案例是结构化日志。 level 、 service 、latency_ms 、trace_id 都在每一行中并且始终是相同类型的值,因此它们都会被粉碎。奇怪的额外对象保留在剩余部分中,仍然可查询,只是速度较慢。陷阱:一行中的 Latency_ms 为 231,下一行中的“231ms”也落入余数。保持价值种类一致。 VARIANT 不仅仅关乎速度。文本对存储的贪婪程度与对 CPU 的贪婪程度一样。我获取了 500 万个事件,并通过三种方式存储相同的数据: CREATE TABLE ev AS SELECT json AS Payload FROM read_ndjson_objects( 'events.ndjson' );创建表 ev AS SELECT json ::VARIANT AS 负载 FROM read_ndjson_objects( 'events.ndjson' );创建表 ev AS SELECT * FROM read_json( 'events.ndjson' );然后每个查询三个查询:两个字段的过滤器、按国家/地区分组的数字字段的总和以及列表查找。 SELECT count ( * ) FROM ev WHERE Payload.type:: VARCHAR = 'purchase' AND Payload.user.country:: VARCHAR = 'FR' ; SELECT Payload.user.country:: VARCHAR AS 国家/地区,总和 (payload.props.amount:: DOUBLE ) AS 金额 FROM ev WHERE Payload.type:: VARCHAR = 'purchase' GROUP BY ALL ORDER BY 1 ; SELECT count ( * ) FROM ev WHERE list_contains(payload.tags:: VARCHAR [], 'c' ); JSON 字符串 VARIANT (2.0 alpha) VARIANT (1.5.5) 每个字段一个类型列 磁盘上 224 MB 85 MB 81 MB 45 MB Q1 筛选器 366 ms 63 ms 4.96 s 52 ms Q2 按国家/地区划分的总和 408 ms 61 m
这篇文章对您有帮助吗?

订阅66必读

每日精选科技资讯,直达你的邮箱