【发布时间】:2020-04-06 08:11:30
【问题描述】:
我在 postgreSQL 数据库上的 SQL 查询遇到了一些问题。
我们正在处理具有 300 000 行的表。
第一个:
SELECT DISTINCT jsonb_object_keys("verbatim_verbatim"."meta") AS "meta_key"
FROM "verbatim_verbatim"
WHERE "verbatim_verbatim"."group_id" = 'dd1c8016-a0ea-49bb-914b-1c036fb3b0a1'::uuid
解释:
HashAggregate (cost=25959.68..32449.08 rows=1278700 width=32) (actual time=274.130..274.144 rows=5 loops=1)
Group Key: jsonb_object_keys(meta)
Buffers: shared hit=18996 read=2308
I/O Timings: read=44.623
-> Seq Scan on verbatim_verbatim (cost=0.00..25766.87 rows=77123 width=32) (actual time=0.048..209.216 rows=390000 loops=1)
Filter: (group_id = 'dd1c8016-a0ea-49bb-914b-1c036fb3b0a1'::uuid)
Rows Removed by Filter: 263605
Buffers: shared hit=18996 read=2308
I/O Timings: read=44.623
Planning time: 103.268 ms
Execution time: 274.385 ms
第二个:
SELECT COUNT(*) AS "__count"
FROM "verbatim_verbatim"
WHERE ("verbatim_verbatim"."group_id" = 'dd1c8016-a0ea-49bb-914b-1c036fb3b0a1'::uuid
AND "verbatim_verbatim"."themes" IS NOT NULL)
解释:
Aggregate (cost=25759.21..25759.22 rows=1 width=8) (actual
time=165.949..165.949 rows=1 loops=1)
Buffers: shared hit=19092 read=2212
I/O Timings: read=52.237
-> Seq Scan on verbatim_verbatim (cost=0.00..25574.06 rows=74059 width=0) (actual time=0.027..161.431 rows=78000 loops=1)
Filter: ((themes IS NOT NULL) AND (group_id = 'dd1c8016-a0ea-49bb-914b-1c036fb3b0a1'::uuid))
Rows Removed by Filter: 263605
Buffers: shared hit=19092 read=2212
I/O Timings: read=52.237
Planning time: 31.154 ms
Execution time: 166.015 ms
按照评论中的建议进行真空分析:
Aggregate (cost=25758.09..25758.10 rows=1 width=8) (actual time=120.529..120.529 rows=1 loops=1)
Buffers: shared hit=20683 read=621
I/O Timings: read=13.179
-> Seq Scan on verbatim_verbatim (cost=0.00..25574.06 rows=73611 width=0) (actual time=0.027..116.082 rows=78000 loops=1)
Filter: ((themes IS NOT NULL) AND (group_id = 'dd1c8016-a0ea-49bb-914b-1c036fb3b0a1'::uuid))
Rows Removed by Filter: 263605
Buffers: shared hit=20683 read=621
I/O Timings: read=13.179
Planning time: 59.956 ms
Execution time: 120.595 ms
这是我的数据库:
create table verbatim_verbatim
(
id serial not null
constraint verbatim_verbatim_pkey
primary key,
verbatim_id varchar(255) not null,
date_interview timestamp with time zone not null,
text varchar(160000) not null,
meta jsonb not null,
themes jsonb,
tonality varchar(8),
group_id uuid not null
constraint verbatim_verbatim_group_id_717c7b4d_fk_verbatim_
references verbatim_verbatimgroup
deferrable initially deferred,
constraint verbatim_verbatim_verbatim_id_group_id_8d53a593_uniq
unique (verbatim_id, group_id)
);
create index verbatim_verbatim_verbatim_id_7e805bd5
on verbatim_verbatim (verbatim_id);
create index verbatim_verbatim_verbatim_id_7e805bd5_like
on verbatim_verbatim (verbatim_id);
create index verbatim_verbatim_meta_89c00a2f
on verbatim_verbatim (meta);
create index verbatim_verbatim_group_id_717c7b4d
on verbatim_verbatim (group_id);
您对优化这些查询有什么想法吗:/? 谢谢你的帮助!
【问题讨论】:
-
请edit您的问题并添加使用
explain (analyze, buffers, format text)生成的execution plan(不是只是一个“简单”解释)为formatted text,并确保您防止缩进计划。粘贴文本,然后将```放在计划前一行和计划后一行。还请包括所有索引的完整create index语句以及(格式化文本,而不是屏幕截图)。 -
除了对函数的调用之外,这个问题可能与 JSONB 没有任何关系。
WHERE子句执行简单的过滤。如果列被索引覆盖,则查询会很快,否则会很慢。在一堆行上执行COUNT(*)总是比为每一行计算一个函数要快。最后,DISTINCT本质上是一个ORDER BY,然后是重复消除。它可以通过索引来加速,除非它必须处理函数结果 - 索引是使用原始数据而不是函数结果构建的。 -
在 PostgreSQL 中,您可以索引 JSON 字段以加速查询,但 this 特定查询正在尝试对字段内容进行扁平化和排序。它不使用任何可以从 JSON 索引中受益的运算符。看起来
meta被用来代替适当的多对多关系。如果您打算在 300K 行上运行它,则必须使用正确的模式。任何其他解决方案都会 slow -
两者都在一秒钟内运行良好(270ms 和 166ms)。但似乎该表的统计信息不是最新的,因为优化器预计第一个查询有 1278700 行,而不仅仅是 5 行。这就是它使用 Seq Scan 的原因,而不是
group_id上的索引。vacuum analyze verbatim_verbatim;有什么改变吗? -
与您的查询性能无关,但为什么您在
(verbatim_id)上有 两个 索引,从屏幕截图看来您也有 两个(group_id)的索引也是如此。不会影响查询性能,但会影响 INSERT、UPDATE 和 DELETE 语句
标签: sql postgresql jsonb