【发布时间】:2020-02-17 19:02:35
【问题描述】:
我来自 Mysql 和 nosql 数据库,我是 Postgress db 的新手。我在 Aurora AWS 上使用 Postgres 11.6。
我正在尝试创建由两列组成的表,一个键和一个 jsonb 值。
每个值如下所示:
{"game": "game6",
"username": "Djobi",
(bunch of fields)
"permissions": ["permission3", "permission1", "permission5"]}
我正在尝试添加不同的索引以查看数据库的容量。其中之一是按用户名查找用户。另一种是寻找具有特定权限的用户。
account_index | account_index_username | CREATE INDEX account_index_username ON public.account_index USING btree (((value -> 'username'::text)))
account_index | account_index_permissions | CREATE INDEX account_index_permissions ON public.account_index USING gin (((value -> 'permissions'::text)))
account_index | account_global_gin | CREATE INDEX accountgin ON public.account_index USING gin (value)
我有两张表,数据完全相同。每个表大约有 3000 万行。一个有索引,一个没有。我正在运行以下查询来测试性能:
SELECT 1
FROM account_noindex
WHERE value @> '{"permissions": ["permission1"]}' limit 10;
我正在这里寻找有权限的用户1。 (旁注,尚不确定如何询问如何获得特别许可 1 与包括许可 1 在内的任何许可) 在我的索引表上运行我的请求时,我得到了 5000 毫秒的响应时间。 在我的非索引表上运行我的请求时,我得到了 50 ms 的响应时间。
所以非索引表比索引表快 100 倍,我不得不说这让我很困惑。 如果我尝试对这两个查询进行解释,我会得到以下结果:
索引表:
Limit (cost=430.49..468.31 rows=10 width=32)
-> Bitmap Heap Scan on account_index (cost=430.49..144146.44 rows=37999 width=32)
Recheck Cond: (value @> '{"permissions": ["permission1"]}'::jsonb)
-> Bitmap Index Scan on accountgin (cost=0.00..420.99 rows=37999 width=0)
Index Cond: (value @> '{"permissions": ["permission1"]}'::jsonb)
(5 rows)
非索引表
Limit (cost=0.00..1935.23 rows=10 width=4)
-> Seq Scan on account_noindex (cost=0.00..7360637.42 rows=38035 width=4)
Filter: (value @> '{"permissions": ["permission1"]}'::jsonb)
如果我尝试更深入地偏移(超过 100k)差异不太明显,但非索引表仍然更快。
[编辑] 这里是索引表的完整分析缓冲区:
EXPLAIN (ANALYZE, BUFFERS) SELECT value->'permissions' FROM account_index WHERE value @> '{"permissions": ["permission1"]}' limit 12;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
Limit (cost=430.49..475.88 rows=12 width=32) (actual time=1926.289..1926.365 rows=12 loops=1)
Buffers: shared hit=24398
-> Bitmap Heap Scan on account_index (cost=430.49..144146.44 rows=37999 width=32) (actual time=1926.287..1926.361 rows=12 loops=1)
Recheck Cond: (value @> '{"permissions": ["permission1"]}'::jsonb)
Rows Removed by Index Recheck: 30
Heap Blocks: lossy=8
Buffers: shared hit=24398
-> Bitmap Index Scan on accountgin (cost=0.00..420.99 rows=37999 width=0) (actual time=1916.655..1916.656 rows=8386144 loops=1)
Index Cond: (value @> '{"permissions": ["permission1"]}'::jsonb)
Buffers: shared hit=24390
Planning Time: 0.073 ms
Execution Time: 1927.143 ms
那么我在这里缺少什么?我是否错误地创建了 GIN 索引?还是我做错了我的要求?
请注意,我的用户名索引也有同样的问题。当请求查找具有特定用户名且没有任何限制的用户时,我会得到一个带或不带 GIN 索引的全表扫描。当我添加 BTREE 索引时,没有问题,不需要限制。
【问题讨论】:
标签: postgresql indexing jsonb gwt-gin