我创建了一个多列索引,在其中索引了同一jsonb列的3个属性。即使where子句使用了确切的3个属性,看起来也没有使用索引。不支持吗?
我正在使用postgres 9.6,并尝试了btree和gin
这是杜松子酒指数
CREATE INDEX custom__observation__multicol
ON fhir.observation USING gin
(((resource -> 'subject'::text) -> 'reference'::text),
(resource -> 'effectiveDateTime'::text),
((resource -> 'code'::text) -> 'coding'::text))
TABLESPACE pg_default;
查询计划如下
Bitmap Heap Scan on observation (cost=600.20..2701.74 rows=1 width=766) (actual time=17749.389..25453.827 rows=1 loops=1)Filter: (is_latest AND (NOT is_deleted) AND ((resource -> 'effectiveDateTime'::text) = to_jsonb('2019-07-31T18:07:52Z'::text)) AND (((resource -> 'subject'::text) ->> 'reference'::text) = 'Patient/e69583dc510c4ed59e362e3ac8c803b5'::text))
Recheck Cond: (((resource -> 'code'::text) -> 'coding'::text) @> '[{"code": "57485005", "system": "http://snomed.info/sct", "display": "Support"}]'::jsonb)
Filter: (is_latest AND (NOT is_deleted) AND ((resource -> 'effectiveDateTime'::text) = to_jsonb('2019-07-31T18:07:52Z'::text)) AND (((resource -> 'subject'::text) ->> 'reference'::text) = 'Patient/e69583dc510c4ed59e362e3ac8c803b5'::text))
Rows Removed by Filter: 93330
Heap Blocks: exact=52088
Buffers: shared hit=373 read=52392 written=25
-> Bitmap Index Scan on custom__observation__nulticol (cost=0.00..600.20 rows=560 width=0) (actual time=65.817..65.817 rows=93331 loops=1)
Index Cond: (((resource -> 'code'::text) -> 'coding'::text) @> '[{"code": "57485005", "system": "http://snomed.info/sct", "display": "Support"}]'::jsonb)
Buffers: shared hit=373 read=304
Planning time: 0.143 ms
Execution time: 25453.872 ms
我还对表运行了analyze命令,但看起来好像没有应用所有三个索引。查询大约需要30秒才能返回pgAdmin
我使用“ CREATE EXTENSION btree_gin”启用了btree_gin 查询计划看起来一样,见下文
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on observation (cost=92.19..2190.12 rows=1 width=768) (actual time=23580.396..31767.965 rows=1 loops=1)
Recheck Cond: (((resource -> 'code'::text) -> 'coding'::text) @> '[{"code": "57485005", "system": "http://snomed.info/sct", "display": "Support"}]'::jsonb)
Filter: (is_latest AND (NOT is_deleted) AND ((resource -> 'effectiveDateTime'::text) = to_jsonb('2019-07-31T18:07:52Z'::text)) AND (((resource -> 'subject'::text) ->> 'reference'::text) = 'Patient/e69583dc510c4ed59e362e3ac8c803b5'::text))
Rows Removed by Filter: 93330
Heap Blocks: exact=52088
Buffers: shared hit=226 read=52372
-> Bitmap Index Scan on custom__observation__multicol (cost=0.00..92.19 rows=559 width=0) (actual time=1304.418..1304.418 rows=93331 loops=1)
Index Cond: (((resource -> 'code'::text) -> 'coding'::text) @> '[{"code": "57485005", "system": "http://snomed.info/sct", "display": "Support"}]'::jsonb)
Buffers: shared hit=226 read=284
Planning time: 1.598 ms
Execution time: 31768.323 ms
根据下面的评论,我创建了两个索引
CREATE INDEX custom__observation__codeindex
ON fhir.observation USING gin
(((resource -> 'code'::text) -> 'coding'::text))
TABLESPACE pg_default;
CREATE INDEX custom__observation__multicol
ON fhir.observation USING btree
(((resource -> 'subject'::text) ->> 'reference'::text) COLLATE pg_catalog."default", (resource ->> 'effectiveDateTime'::text) COLLATE pg_catalog."default")
TABLESPACE pg_default;
查询速度更快,这是查询计划
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on observation (cost=834.97..890.83 rows=1 width=767) (actual time=2599.083..3460.635 rows=1 loops=1)
Recheck Cond: ((((resource -> 'code'::text) -> 'coding'::text) @> '[{"code": "57485005", "system": "http://snomed.info/sct", "display": "Support"}]'::jsonb) AND (((resource -> 'subject'::text) ->> 'reference'::text) = 'Patient/e69583dc510c4ed59e362e3ac8c803b5'::text))
Filter: (is_latest AND (NOT is_deleted) AND ((resource -> 'effectiveDateTime'::text) = to_jsonb('2019-07-31T18:07:52Z'::text)))
Rows Removed by Filter: 2331
Heap Blocks: exact=2286
Buffers: shared hit=217 read=2720
-> BitmapAnd (cost=834.97..834.97 rows=14 width=0) (actual time=1241.916..1241.916 rows=0 loops=1)
Buffers: shared hit=217 read=434
-> Bitmap Index Scan on custom__observation__codeindex (cost=0.00..128.19 rows=559 width=0) (actual time=951.950..951.950 rows=93331 loops=1)
Index Cond: (((resource -> 'code'::text) -> 'coding'::text) @> '[{"code": "57485005", "system": "http://snomed.info/sct", "display": "Support"}]'::jsonb)
Buffers: shared hit=217 read=284
-> Bitmap Index Scan on custom__observation__multicol (cost=0.00..706.52 rows=14130 width=0) (actual time=137.624..137.624 rows=13985 loops=1)
Index Cond: (((resource -> 'subject'::text) ->> 'reference'::text) = 'Patient/e69583dc510c4ed59e362e3ac8c803b5'::text)
Buffers: shared read=150
Planning time: 5.311 ms
Execution time: 3460.907 ms
(16 rows)
似乎两个索引的工作效果更好,但是multi col索引未应用有效的DateTime属性,因此这基本上仍然是相同的问题,但现在具有两个而不是三个属性。
答案 0 :(得分:0)
为支持此查询,我建议两个不同的索引:
一个支持@>
运算符的索引:
CREATE INDEX ON fhir.observation USING gin ((resource -> 'code') -> 'coding'));
还有一个BTree索引来支持标量值上的=
运算符:
CREATE INDEX
ON fhir.observation ( (resource -> 'subject' -> 'reference'), (resource -> 'effectiveDateTime') );
第二和第三个表达式不使用多列索引的原因是仅GIN索引supports the operators:?
,?&
,?|
和{ {1}}。
因此,GIN索引不能用于使用@>
的表达式。
这就是为什么相等条件需要第二个BTree索引的原因。