create index library_params_btree on library using btree(params); explain analyze select * from library where params @> '{"catalog":[{"name": "TldvTAsvuM"}]}';查询结构如下没有走索引
Gather (cost=1000.00..44061.33 rows=100 width=275) (actual time=402.955..405.912 rows=1 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on library (cost=0.00..43051.33 rows=42 width=275) (actual time=392.910..392.977 rows=0 loops=3) " Filter: (params @> '{""catalog"": [{""name"": ""TldvTAsvuM""}]}'::jsonb)" Rows Removed by Filter: 333333 Planning Time: 0.276 ms Execution Time: 405.927 ms采用整个列的内容进行查询,使用了索引
explain analyze select * from library where params = '{"catalog": [{"name": "TldvTAsvuM"}, {"name": "UOLFmReEXC"}]}'; Index Scan using library_params_btree on library (cost=0.68..8.69 rows=1 width=275) (actual time=0.079..0.080 rows=1 loops=1) " Index Cond: (params = '{""catalog"": [{""name"": ""TldvTAsvuM""}, {""name"": ""UOLFmReEXC""}]}'::jsonb)" Planning Time: 0.061 ms Execution Time: 0.093 ms对字段进行索引
create index library_params_btree_params_catalog on library using btree((params->>'catalog')); explain analyze select * from library where params ->> 'catalog' = '[{"name": "TldvTAsvuM"}, {"name": "UOLFmReEXC"}]'; Bitmap Heap Scan on library (cost=619.42..14503.62 rows=5000 width=275) (actual time=0.027..0.028 rows=1 loops=1) " Recheck Cond: ((params ->> 'catalog'::text) = '[{""name"": ""TldvTAsvuM""}, {""name"": ""UOLFmReEXC""}]'::text)" Heap Blocks: exact=1 -> Bitmap Index Scan on library_params_btree_params_catalog (cost=0.00..618.17 rows=5000 width=0) (actual time=0.024..0.024 rows=1 loops=1) " Index Cond: ((params ->> 'catalog'::text) = '[{""name"": ""TldvTAsvuM""}, {""name"": ""UOLFmReEXC""}]'::text)" Planning Time: 0.063 ms Execution Time: 0.044 ms使用@>操作符也不会走索引
explain analyze select * from library where params @> '{"catalog":[{"name": "KftNvvdQgn"}, {"name": "kcNwEkPmJy"}]}';gin索引
The -> Document 1, Document 2 Quick -> Document 1 Brown -> Document 1 Fox -> Document 1 Jumped -> Document 1 Over -> Document 1 Lazy -> Document 1, Document 2 Dog -> Document 1, Document 2 Slept -> Document 2 In -> Document 2 Sun -> Document 2
json、jsonb推荐gin索引的原因不只是搜索的方便,还以为索引自由模式。
create index library_params_gin on library using gin(params);运行下面两条查询语句,都进行了索引搜索:
explain analyze select * from library where params ? '{"catalog":[{"name": "KftNvvdQgn"}, {"name": "kcNwEkPmJy"}]}'; explain analyze select * from library where params @> '{"catalog": [{"name": "TldvTAsvuM"}, {"name": "UOLFmReEXC"}]}';gin索引类型
explain analyze select * from library where params @> '{"catalog":[{"name": "KftNvvdQgn"}, {"name": "kcNwEkPmJy"}]}';例如使用->来查询:并不会走索引
explain analyze select * from library where params -> 'catalog'?'[{"name": "KftNvvdQgn"}, {"name": "kcNwEkPmJy"}]'; Gather (cost=1000.00..46093.00 rows=10000 width=275) (actual time=85.055..87.858 rows=0 loops=1) Workers Planned: 2 Workers Launched: 2 -> Parallel Seq Scan on library (cost=0.00..44093.00 rows=4167 width=275) (actual time=74.086..74.086 rows=0 loops=3) " Filter: ((params -> 'catalog'::text) ? '[{""name"": ""KftNvvdQgn""}, {""name"": ""kcNwEkPmJy""}]'::text)" Rows Removed by Filter: 333333 Planning Time: 0.099 ms Execution Time: 87.874 ms如果需要对params->'catalog'的查询使用索引,在索引建立的时候要使用params->'catalog'
create index library_params_gin_params_catalog on library using gin((params->'catalog')); explain analyze select * from library where params -> 'catalog'?'[{"name": "KftNvvdQgn"}, {"name": "kcNwEkPmJy"}]'; Bitmap Heap Scan on library (cost=113.50..22793.12 rows=10000 width=275) (actual time=0.016..0.016 rows=0 loops=1) " Recheck Cond: ((params -> 'catalog'::text) ? '[{""name"": ""KftNvvdQgn""}, {""name"": ""kcNwEkPmJy""}]'::text)" -> Bitmap Index Scan on library_params_gin_params_catalog (cost=0.00..111.00 rows=10000 width=0) (actual time=0.014..0.014 rows=0 loops=1) " Index Cond: ((params -> 'catalog'::text) ? '[{""name"": ""KftNvvdQgn""}, {""name"": ""kcNwEkPmJy""}]'::text)" Planning Time: 0.193 ms Execution Time: 0.033 ms而使用=进行比较的话也不会走索引
explain analyze select * from library where params -> 'catalog'='[{"name": "KftNvvdQgn"}, {"name": "kcNwEkPmJy"}]';也可以使用@?
explain analyze select * from library where params @? ('($.catalog[*] ?(@.name == "KftNvvdQgn"))');但是如果在json path上使用json path处理函数的话,就无法使用索引了
explain analyze select * from library where params @? ('($.catalog[*].size() == "2")'); Seq Scan on library (cost=0.00..50343.00 rows=999900 width=275) (actual time=0.010..949.993 rows=1000000 loops=1) " Filter: (params @? '($.""catalog""[*].size() == ""2"")'::jsonpath)" Planning Time: 0.181 ms Execution Time: 976.060 msJSONB_PATH_OPS
create index library_params_gin_params_catalog_jsonb_path_ops on library using gin(params JSONB_PATH_OPS);下面两个语句不会使用索引
explain analyze select * from library where params ? '{"catalog":[{"name": "KftNvvdQgn"}, {"name": "kcNwEkPmJy"}]}'; explain analyze select * from library where params ?| '{"catalog"}';下面两个语句会使用索引
explain analyze select * from library where params @> '{"catalog":[{"name": "KftNvvdQgn"}, {"name": "kcNwEkPmJy"}]}'; explain analyze select * from library where params @? ('($.catalog[*] ?(@.name == "KftNvvdQgn"))');JSONB_OPS和JSONB_PATH_OPS的区别
尽管jsonb_path_ops操作符类只支持用 @>,@@和@?操作符的查询,但它比起默认的操作符类 jsonb_ops有更客观的性能优势。一个 jsonb_path_ops索引通常也比一个相同数据上的 jsonb_ops要小得多,并且搜索的专一性更好,特 别是当查询包含频繁出现在该数据中的键时。因此,其上的搜索操作 通常比使用默认操作符类的搜索表现更好。
jsonb_ops和jsonb_path_ops GIN 索引之间的技术区别是前者为数据中的每一个键和值创建独立的索引项, 而后者值为该数据中的每个值创建索引项。 基本上,每一个jsonb_path_ops索引项是其所对应的值和 键的哈希。例如要索引{"foo": {"bar": "baz"}},将创建一个 单一的索引项,它把所有三个foo、bar、 和baz合并到哈希值中。因此一个查找这个结构的包含查询可能 导致极度详细的索引搜索。但是根本没有办法找到foo是否作为 一个键出现。在另一方面,一个jsonb_ops会创建三个索引 项分别表示foo、bar和baz。那么要 做同样的包含查询,它将会查找包含所有三个项的行。虽然 GIN 索引能够相当 有效地执行这种 AND 搜索,它仍然不如等效的 jsonb_path_ops搜索那样详细和快速(特别是如果有大量 行包含三个索引项中的任意一个时)。
create table library(id bigserial primary key , params jsonb, delete_status bool ); create index library_params_gin on library using gin(params);params格式,其中数组长度{2-12}随机
{"catalog": [{"name": "KftNvvdQgn"}, {"name": "kcNwEkPmJy"}]}使用navicat生成数据,DML语句后续给出。