我对具有150万行的表进行了相对简单的查询:
SELECT mtid FROM publication
WHERE mtid IN (9762715) OR last_modifier=21321
LIMIT 5000;
EXPLAIN ANALYZE
输出:
Limit (cost=8.84..12.86 rows=1 width=8) (actual time=0.985..0.986 rows=1 loops=1) -> Bitmap Heap Scan on publication (cost=8.84..12.86 rows=1 width=8) (actual time=0.984..0.985 rows=1 loops=1) Recheck Cond: ((mtid = 9762715) OR (last_modifier = 21321)) -> BitmapOr (cost=8.84..8.84 rows=1 width=0) (actual time=0.971..0.971 rows=0 loops=1) -> Bitmap Index Scan on publication_pkey (cost=0.00..4.42 rows=1 width=0) (actual time=0.295..0.295 rows=1 loops=1) Index Cond: (mtid = 9762715) -> Bitmap Index Scan on publication_last_modifier_btree (cost=0.00..4.42 rows=1 width=0) (actual time=0.674..0.674 rows=0 loops=1) Index Cond: (last_modifier = 21321) Total runtime: 1.027 ms
到目前为止,一切都很好,速度很快,并使用了可用的索引。
现在,如果我稍微修改一下查询,结果将是:
SELECT mtid FROM publication
WHERE mtid IN (SELECT 9762715) OR last_modifier=21321
LIMIT 5000;
该EXPLAIN ANALYZE
输出是:
Limit (cost=0.01..2347.74 rows=5000 width=8) (actual time=2735.891..2841.398 rows=1 loops=1) -> Seq Scan on publication (cost=0.01..349652.84 rows=744661 width=8) (actual time=2735.888..2841.393 rows=1 loops=1) Filter: ((hashed SubPlan 1) OR (last_modifier = 21321)) SubPlan 1 -> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=1) Total runtime: 2841.442 ms
没那么快,并且使用seq scan ...
当然,由应用程序运行的原始查询会更复杂,甚至更慢,当然,休眠生成的原始查询不会(SELECT 9762715)
,但是即使如此,它也存在缓慢(SELECT 9762715)
!该查询是由休眠生成的,因此更改它们是很大的挑战,并且某些功能不可用(例如UNION
,不可用,那会很快)。
问题
- 为什么在第二种情况下不能使用索引?如何使用它们?
- 我可以通过其他方式提高查询性能吗?
其他想法
似乎我们可以通过手动执行SELECT来使用第一种情况,然后将结果列表放入查询中。即使IN()列表中有5000个数字,它也比第二种解决方案快四倍。但是,这似乎是错误的(而且,它可能快100倍:))。为什么查询计划者对这两个查询使用完全不同的方法是完全无法理解的,所以我想找到一个更好的解决方案。
(SELECT 9762715)
。
(SELECT 9762715)
。对于休眠问题:可以做到这一点,但需要认真重写代码,因为我们拥有用户定义的休眠标准查询,这些查询是即时翻译的。因此,从本质上讲,我们将修改休眠状态,这是一项艰巨的任务,并且会带来许多可能的副作用。
JOIN
而不是IN ()
吗?另外,publication
最近有分析吗?