鉴于 PostgreSQL 13.3 表和数据
CREATE TABLE transaction (message jsonb NOT NULL);
INSERT INTO transaction(message) VALUES ('{"amount": 1.00}'), ('{"amount": 2.00}');
索引
CREATE INDEX ON transaction (((message->'amount')::numeric));
用于查询
SELECT t.message FROM transaction t
WHERE (t.message->'amount')::numeric > 1.00;
两个索引都没有
CREATE INDEX ON transaction USING GIN (message);
CREATE INDEX ON transaction USING GIN (message jsonb_path_ops);
用于查询
SELECT t.message FROM transaction t
WHERE t.message @@ format('$.amount > %s', 1.00)::jsonpath;
PostgreSQL 中有没有办法对
transaction.message
列进行索引,以便 JSONPath @@
运算符使用索引而不是进行 Seq Scan?
我认为表中没有足够的行来使用索引。禁用会话的顺序扫描或尝试此操作
CREATE TABLE transaction (message jsonb NOT NULL);
INSERT INTO transaction(message) VALUES ('{"amount": 1.00}'), ('{"amount": 2.00}');
INSERT INTO transaction (message) SELECT ('{"amount": '|| random() * 100 || '}')::jsonb FROM generate_series(1, 1000);
CREATE INDEX ON transaction (((message->'amount')::numeric));
现在使用索引了
EXPLAIN ANALYZE SELECT t.message-> 'amount' FROM transaction t WHERE (t.message->'amount')::numeric = 1.00;
退货
Bitmap Heap Scan on transaction t (cost=4.31..12.41 rows=5 width=32) (actual time=0.260..0.328 rows=1 loops=1)
Recheck Cond: (((message -> 'amount'::text))::numeric = 1.00)
Heap Blocks: exact=1
-> Bitmap Index Scan on transaction_numeric_idx (cost=0.00..4.31 rows=5 width=0) (actual time=0.226..0.237 rows=1 loops=1)
Index Cond: (((message -> 'amount'::text))::numeric = 1.00)
Planning Time: 0.131 ms
Execution Time: 0.448 ms
仍然选择顺序扫描
SELECT t.message-> 'amount' FROM transaction t WHERE (t.message->'amount')::numeric > 1.00
因为规划者在统计中看到太多> 1.00 的值。
问题的其他部分也一样。
CREATE INDEX ON transaction USING GIN (message jsonb_path_ops);
EXPLAIN ANALYZE SELECT t.message FROM transaction t WHERE t.message @@ '$.amount == 1.00';
退货
Bitmap Heap Scan on transaction t (cost=8.01..12.02 rows=1 width=36) (actual time=0.103..0.141 rows=1 loops=1)
Recheck Cond: (message @@ '($.""amount"" == 1.00)'::jsonpath)"
Heap Blocks: exact=1
-> Bitmap Index Scan on transaction_message_idx (cost=0.00..8.01 rows=1 width=0) (actual time=0.051..0.061 rows=1 loops=1)
Index Cond: (message @@ '($.""amount"" == 1.00)'::jsonpath)"
Planning Time: 0.120 ms
Execution Time: 0.227 ms