2017-09-01 69 views
-1

給定一個表Postgres的9.4+ jsonb:指數詞典嵌套在陣列

create table tmp (data jsonb not null); 

和數據

insert into tmp (data) values ('{"root": [{"name": "item1"}, {"name": "item2"}]}'); 

我需要指數jsonb列 '數據' 快速回答查詢,如

select * from tmp where data->'root' @> '[{"name": "item1"}]'; 

Postgres 9.4+有可能嗎?

+1

'CREATE INDEX ON tmp((dat一個 - >> '根'));'? – Hackerman

+0

@Hackerman你已經接近了:正確的解決方案似乎是'data - >'root''。 – user2740947

回答

0

經過一些調試後,我瞭解到爲外部json元素(例如「root」)創建的索引也適用於層次結構中的所有嵌套元素。所以在我的情況下,正確的辦法是:

CREATE INDEX idx_tmp_data_root ON tmp USING gin ((data->'root') jsonb_path_ops); 

我選擇了jsonb_path_ops索引操作符類,因爲它支持的要求,並在更緊湊和更快的指數結果,而不是默認的索引類型遏制查詢@>

這裏是一個充分的論證:

首先,創建一個表並加載數據:

-> SET enable_seqscan = OFF; -- force postgres to use indices if any 
-> create temporary table tmp (data jsonb not null); 
-> insert into tmp (data) values ('{"root": [{"name": "item1"}, {"name": "item2"}]}'); 

查詢沒有索引:

-> explain select * from tmp where data->'root' @> '[{"name": "item1"}]'; 

QUERY PLAN 
Seq Scan on tmp (cost=10000000000.00..10000000029.65 rows=1 width=32) 
    Filter: ((data -> 'root'::text) @> '[{"name": "item1"}]'::jsonb) 
(2 rows) 

查詢與索引:

-> CREATE INDEX idx_tmp_data_root ON tmp USING gin ((data->'root') jsonb_path_ops); 
-> explain select * from tmp where data->'root' @> '[{"name": "item1"}]'; 

QUERY PLAN 
Bitmap Heap Scan on tmp (cost=8.00..12.02 rows=1 width=32) 
    Recheck Cond: ((data -> 'root'::text) @> '[{"name": "item1"}]'::jsonb) 
    -> Bitmap Index Scan on idx_tmp_data_root (cost=0.00..8.00 rows=1 width=0) 
    Index Cond: ((data -> 'root'::text) @> '[{"name": "item1"}]'::jsonb) 
(4 rows) 

-> SET enable_seqscan = ON;