Postgresql

时间:2015-04-30 11:38:13

标签: postgresql join

所以,我在postgresql数据库中有两个表,一个名为foo,结构如下:

Column | Type
-------------
id     | integer
raw    | json

另一个名为bar,看起来像这样:

Column | Type
-------------
id     | integer
action | character varying

foo的表达式索引如下所示:"foo_expr_idx" btree ((raw ->> 'action'::text))

此索引有效。尽管foo有数百万行,但我可以运行如下查询:

SELECT * from foo WHERE raw->>'action' = 'open'

它使用索引而不执行顺序扫描。我使用EXPLAIN ANALYZE验证了这一点。

但是当我在连接中使用该表达式时,它不使用索引。所以加入如:

SELECT * from bar LEFT OUTER JOIN foo ON (bar.action = foo.raw->>'action'); 

非常缓慢。当我检查它在做什么时,肯定会进行顺序扫描。如何让postgresql在这样的连接中使用表达式索引?

解释的输出如下:

Merge Left Join  (cost=1101140.74..1207570.52 rows=5560478 width=175)        (actual time=815671.230..873493.479 rows=16673 loops=1)
   Output: bar.id, bar.action, foo.id, foo.raw, 
   Merge Cond: ((bar.action)::text = ((foo.raw ->> 'action'::text)))
   ->  Sort  (cost=1719.29..1745.81 rows=10607 width=131) (actual  time=47.439..60.859 rows=10628 loops=1)
       Output: bar.id, bar.action
       Sort Key: bar.action
       Sort Method: external merge  Disk: 1024kB
       ->  Seq Scan on public.bar  (cost=0.00..282.07 rows=10607 width=131) (actual time=0.008..10.186 rows=10628 loops=1)
           Output: bar.id, bar.action
   ->  Materialize  (cost=1099421.45..1117505.18 rows=3616747 width=44) (actual time=815623.382..864899.131 rows=3614363 loops=1)
           Output: foo.id, foo.raw, ((foo.raw ->> 'action'::text))
           ->  Sort  (cost=1099421.45..1108463.31 rows=3616747 width=44) (actual time=815623.356..851265.324 rows=3608287 loops=1)
               Output: foo.id, foo.raw, ((foo.raw ->> 'action'::text))
               Sort Key: ((foo.raw ->> 'action'::text))
               Sort Method: external merge  Disk: 2611952kB
               ->  Seq Scan on public.foo  (cost=0.00..371670.47 rows=3616747 width=44) (actual time=0.052..121762.195 rows=3612522 loops=1)
                   Output: foo.id, foo.raw, (foo.raw ->> 'action'::text)
  Total runtime: 874110.670 ms
 (18 rows)

1 个答案:

答案 0 :(得分:0)

问题似乎是Postgresql对那些不合适的数据做了一些假设。简单的解决方案是分析表格......

运行后

analyze foo;

我的查询运行时间从14分钟下降到259毫秒。