我有一个带有jsonb
字段的表。实际上,一维数组存储在此处-一些ID的列表,如下所示:
[254622, 301359, 309207, 334299, 351963, 355482, 350938]
此字段也有一个索引:
CREATE INDEX users_log_actions_idx ON public.users_list_orders
USING gin (users_log_actions);
在我的查询中,我通过该字段(简化版本,没有WHERE的条件)进行搜索:
SELECT *
FROM
users_list_orders
WHERE
users_list_orders.user_id != '239118'
AND
NOT ( users_log_actions @> '239118' )
问题是:我的应用程序每秒执行数百个类似的查询(当然,使用不同的用户ID),有时此查询非常快(大约0.2秒),有时非常慢(> 15秒)。我发现瓶颈是按jsonb字段(users_log_actions)进行搜索,所以我很感激任何有关如何加快此速度的建议。
更新:
对此查询进行解释(分析,缓冲区,格式化文本):
Limit (cost=1.36..53.32 rows=1 width=313) (actual time=0.470..0.473 rows=1 loops=1)
Buffers: shared hit=25
InitPlan 2 (returns $1)
-> Result (cost=0.50..0.51 rows=1 width=4) (actual time=0.100..0.101 rows=1 loops=1)
Buffers: shared hit=5
InitPlan 1 (returns $0)
-> Limit (cost=0.42..0.50 rows=1 width=4) (actual time=0.097..0.098 rows=1 loops=1)
Buffers: shared hit=5
-> Index Only Scan Backward using users_list_orders_pkey on users_list_orders users_list_orders_1 (cost=0.42..39525.78 rows=503412 width=4) (actual time=0.096..0.097 rows=1 loops=1)
Index Cond: (id IS NOT NULL)
Heap Fetches: 1
Buffers: shared hit=5
-> Nested Loop (cost=0.84..102524.47 rows=1973 width=313) (actual time=0.469..0.470 rows=1 loops=1)
Buffers: shared hit=25
-> Index Scan using public_users_list_orders_order_category_id2_idx on users_list_orders (cost=0.42..75900.87 rows=15889 width=312) (actual time=0.426..0.426 rows=1 loops=1)
Index Cond: (order_category_id = '18'::smallint)
Filter: ((user_id <> 239118) AND (order_reported <= '50'::smallint) AND (NOT (users_log_actions @> '239118'::jsonb)) AND (NOT (users_log_hidden @> '239118'::jsonb)) AND (order_active = 1) AND ((order_daily_limit = 0) OR (order_daily_counter < order_daily_limit)) AND ((order_overall_limit = 0) OR (order_overall_counter < order_overall_limit)) AND ((id)::double precision >= round((random() * ($1)::double precision))))
Rows Removed by Filter: 4
Buffers: shared hit=21
-> Index Scan using users_main_pkey on users_main (cost=0.42..1.67 rows=1 width=9) (actual time=0.041..0.041 rows=1 loops=1)
Index Cond: (id = users_list_orders.user_id)
Filter: ((user_balance_usd > 0.05) AND (users_list_orders.order_price_usd < user_balance_usd))
Buffers: shared hit=4
Planning time: 2.209 ms
Execution time: 0.559 ms