为什么这个查询在JSONB Gin索引字段上花了这么长时间?我可以修复它以便实际使用索引吗?

时间:2016-10-31 23:19:19

标签: sql postgresql indexing jsonb

最近我们将其中一个表的格式从使用列中的单个条目更改为具有[“key1”,“key2”,“key3”]等格式的JSONB列。虽然我们构建了一个GIN在JSONB字段上的索引我们在其上使用的查询非常慢(在解释计划中的50分钟范围内)。我试图找到一种方法来优化查询并正确使用索引。我粘贴了下面的查询以及它的解释计划。索引字段是visit.visitor,launch.campaign_key,launch.launch_key,visit.store_key和visits.stop JSONB字段作为GIN索引。我们正在使用PostgresQL 9.4

explain (analyze on) select count(subselect.visitors) as visitors,
subselect.campaign as campaign 
from (
    select distinct visit.visitor as visitors,
          launch.campaign_key as campaign 
from visit 
    join launch on (jsonb_exists(visit.stops, launch.launch_key)) where 
       visit.store_key = 'ahBzfmdlYXJsYXVuY2gtaHVi' 
       and launch.state = 'PRODUCTION') as subselect group by subselect.campaign

解释结果:

HashAggregate  (cost=63873548.47..63873550.47 rows=200 width=88) (actual time=248617.348..248617.365 rows=58 loops=1)
  Group Key: launch.campaign_key
  ->  HashAggregate  (cost=63519670.22..63661221.52 rows=14155130 width=88) (actual time=248587.320..248616.558 rows=1938 loops=1)
    Group Key: visit.visitor, launch.campaign_key
    ->  HashAggregate  (cost=63307343.27..63448894.57 rows=14155130 width=88) (actual time=248553.278..248584.868 rows=1938 loops=1)
          Group Key: visit.visitor, launch.campaign_key
          ->  Nested Loop  (cost=4903.09..56997885.96 rows=1261891461 width=88) (actual time=180648.410..248550.249 rows=2085 loops=1)
                Join Filter: jsonb_exists(visit.stops, (launch.launch_key)::text)
                Rows Removed by Join Filter: 624114512
                ->  Bitmap Heap Scan on launch  (cost=3213.19..126084.38 rows=169389 width=123) (actual time=32.082..317.561 rows=166121 loops=1)
                      Recheck Cond: ((state)::text = 'PRODUCTION'::text)
                      Heap Blocks: exact=56635
                      ->  Bitmap Index Scan on launch_state_idx  (cost=0.00..3170.85 rows=169389 width=0) (actual time=21.172..21.172 rows=166121 loops=1)
                            Index Cond: ((state)::text = 'PRODUCTION'::text)
                ->  Materialize  (cost=1689.89..86736.04 rows=22349 width=117) (actual time=0.000..0.487 rows=3757 loops=166121)
                      ->  Bitmap Heap Scan on visit  (cost=1689.89..86624.29 rows=22349 width=117) (actual time=1.324..14.381 rows=3757 loops=1)
                            Recheck Cond: ((store_key)::text = 'ahBzfmdlYXJsYXVuY2gtaHVicg8LEgVTdG9yZRinzbKcDQw'::text)
                            Heap Blocks: exact=3672
                            ->  Bitmap Index Scan on visit_store_key_idx  (cost=0.00..1684.31 rows=22349 width=0) (actual time=0.780..0.780 rows=3757 loops=1)
                                  Index Cond: ((store_key)::text = 'ahBzfmdlYXJsYXVuY2gtaHVicg8LEgVTdG9yZRinzbKcDQw'::text)
Planning time: 0.232 ms
Execution time: 248708.088 ms

我应该提一下关于stop的索引     CREATE INDEX ON访问使用GIN(停止)

我想知道是否转而构建它     CREATE INDEX ON访问使用GIN(停止 - >'值')

会解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

包装函数 let userNum = Int(usernumInput.text!) for i in 1...<=userNum { if i % 2 == 0 { print(i) } } 阻止在jsonb_exists()上使用gin索引。而不是

visits.stops

尝试

from visit 
join launch on (jsonb_exists(visit.stops, launch.launch_key))