在我的笔记本电脑上运行PostgreSQL 9.6.4,我有一个叫node
有主键id
字段和 properties::jsonb
字段的表.
我在该properties
字段上设置了GIN索引.
当我运行此查询时:
SELECT n.*
FROM node n
WHERE node_type_id = '2'
AND properties @> '{"slug":"wild-castles"}'::JSONB
ORDER BY n.id ASC OFFSET 0 LIMIT 10;
Run Code Online (Sandbox Code Playgroud)
在~5M行表上,获得答案大约需要20秒.查看解释计划,我发现查询优化器首先按主键对表进行排序,然后按properties
字段过滤:
Limit (cost=0.56..1517.94 rows=10 width=154)
-> Index Scan using node_pkey on node n (cost=0.56..739571.11 rows=4874 width=154)
Filter: ((properties @> '{"slug": "wild-castles"}'::jsonb) AND ((node_type_id)::text = '2'::text))
Run Code Online (Sandbox Code Playgroud)
但当我删除顺序时,我看到优化器使用索引按预期方式:
SELECT n.*
FROM node n
WHERE node_type_id = '2'
AND properties @> '{"slug":"wild-castles"}'::JSONB
OFFSET 0 LIMIT 10;
Limit (cost=93.77..127.10 rows=10 width=154)
-> Bitmap Heap Scan on node n (cost=93.77..16338.56 rows=4874 width=154)
Recheck Cond: (properties @> '{"slug": "wild-castles"}'::jsonb)
Filter: ((node_type_id)::text = '2'::text)
-> Bitmap Index Scan on node_ix02 (cost=0.00..92.55 rows=4874 width=0)
Index Cond: (properties @> '{"slug": "wild-castles"}'::jsonb)
Run Code Online (Sandbox Code Playgroud)
此外,一个简单的WHERE properties @> '{"slug":"wild-castles"}'::JSONB
行为符合预期:
EXPLAIN SELECT n.*
FROM node n
WHERE properties @> '{"slug":"wild-castles"}'::JSONB
;
Bitmap Heap Scan on node n (cost=93.77..16326.38 rows=4874 width=154)
Recheck Cond: (properties @> '{"slug": "wild-castles"}'::jsonb)
-> Bitmap Index Scan on node_ix02 (cost=0.00..92.55 rows=4874 width=0)
Index Cond: (properties @> '{"slug": "wild-castles"}'::jsonb)
Run Code Online (Sandbox Code Playgroud)
所以我想我想知道为什么优化器不会先使用索引来过滤掉行,然后按id
字段对它们进行排序?
更改Planner 方法配置并强制 planner 不执行 seqscan
例如
SET enable_seqscan = OFF;
SELECT n.*
FROM node n
WHERE node_type_id = '2'
AND properties @> '{"slug":"wild-castles"}'::JSONB
ORDER BY n.id ASC OFFSET 0 LIMIT 10;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
239 次 |
最近记录: |