postgresql - Postgresql 下的连接中未使用 JSON 表达式索引

标签 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 在这样的连接中使用表达式索引?

explain 的输出如下所示:

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)

最佳答案

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

运行后

analyze foo;

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

关于postgresql - Postgresql 下的连接中未使用 JSON 表达式索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29966722/

相关文章:

sql - 在左侧外连接的右侧表上添加过滤器

MySQL 左连接使用默认值

MySQL:在一对一的基础上加入

mysql - 按另一个表的计数选择记录顺序,未在 Mysql 中检索正确的计数

postgresql - postgres 数据库文件 - 哪个文件代表特定的表/索引?

sql - 有没有办法通过 IN 列表中的值来限制查询结果?

postgresql - 分隔查询位置

postgresql - gem install pg --with-pg-config 有效, bundle 失败

python - 有没有办法让 psycopg2 将点作为 python 元组返回?

powershell - 在PowerShell中使用换行符连接数组