Postgresql 在JSONB列上添加GIN索引会减慢我的请求
我来自Mysql和nosql数据库,我是Postgress db的新手。我正在Aurora AWS上使用Postgres 11.6 我试图创建由两列组成的表,一个键和一个jsonb值 每个值如下所示:Postgresql 在JSONB列上添加GIN索引会减慢我的请求,postgresql,indexing,jsonb,gwt-gin,Postgresql,Indexing,Jsonb,Gwt Gin,我来自Mysql和nosql数据库,我是Postgress db的新手。我正在Aurora AWS上使用Postgres 11.6 我试图创建由两列组成的表,一个键和一个jsonb值 每个值如下所示: {"game": "game6", "username": "Djobi", (bunch of fields) "permissions": ["permission3", "permission1", "permission5"]} 我试图添加不同的索引,以查看数据库
{"game": "game6",
"username": "Djobi",
(bunch of fields)
"permissions": ["permission3", "permission1", "permission5"]}
我试图添加不同的索引,以查看数据库的容量。其中之一,就是通过用户名查找用户。另一个是查找具有特定权限的用户
account_index | account_index | username |在public.account_index上创建索引account_index_username |使用btree(((value->“username”::text))进行索引)
account_index | account_index | permissions |在public.account_索引上创建索引account_index(使用gin(((值->‘权限’::text))的权限)
account_index | account_global_gin |使用gin(值)在public.account_索引上创建索引accountgin
我有两张表,数据完全相同。每个表大约有3000万行。一个有索引,一个没有。我正在运行以下查询以测试性能:
SELECT 1
FROM account_noindex
WHERE value @> '{"permissions": ["permission1"]}' limit 10;
我在这里尝试查找具有权限1的用户。(旁注,尚不确定如何询问具体许可1与包括许可1在内的任何许可)
在索引表上运行请求时,响应时间为5000ms。
在我的非索引表上运行请求时,我得到了50毫秒的响应时间
所以非索引表比索引表快100倍,这让我很困惑。
如果我尝试对这两个查询进行解释,我会得到以下结果:
索引表:
限制(成本=430.49..468.31行=10宽=32)
->帐户索引上的位图堆扫描(成本=430.49..144146.44行=37999宽度=32)
重新检查条件:(值@>'{“权限”:[“权限1”]}'::jsonb)
->accountgin上的位图索引扫描(成本=0.00..420.99行=37999宽度=0)
索引条件:(value@>'{“permissions”:[“permission1”]}'::jsonb)
(5排)
非索引表
限制(成本=0.00..1935.23行=10宽=4)
->按账户扫描索引(成本=0.00..7360637.42行=38035宽度=4)
筛选器:(值@>'{“权限”:[“权限1”]}'::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索引时,没有问题,也不需要限制。JSONB列没有收集到有用的统计数据。该数据库必须对满足@>的行数进行一般性假设,而这些假设通常是错误的。在决定进行限额查询的绝对最佳方式时,拥有更准确的统计信息非常重要。一般的假设是@>将匹配表的0.1%。如果这对你的情况来说是严重错误的,你很可能会得到糟糕的计划 尽管两个计划之间的差异看起来确实非常大。如果没有SEED
解释(分析、缓冲)
就很难具体说明这一点
注意,我的用户名上的索引也有同样的问题。如果我只是有杜松子酒指数,我会得到非常奇怪的结果。当我添加BTREE索引时,就没有问题了
我不知道“奇怪”的结果可能是什么。你必须提供一些例子。谢谢,我编辑了原文来解释另一个奇怪之处。我想原因和你解释的差不多。我还添加了分析。