AnA*_*ice 4 sql postgresql indexing performance postgresql-performance
我正在使用Postgres 9.1并且查询速度非常慢.
Explain Analyze SELECT COUNT(DISTINCT email) FROM "invites" WHERE (
created_at < '2012-10-10 21:08:05.259200'
AND invite_method = 'email'
AND accept_count = 0
AND reminded_count < 3
AND (last_reminded_at IS NULL OR last_reminded_at < '2012-10-10 21:08:05.261483'))
Run Code Online (Sandbox Code Playgroud)
Aggregate (cost=19828.24..19828.25 rows=1 width=21) (actual time=11395.903..11395.903 rows=1 loops=1)
-> Seq Scan on invites (cost=0.00..18970.57 rows=343068 width=21) (actual time=0.036..353.121 rows=337143 loops=1)
Filter: ((created_at < '2012-10-10 21:08:05.2592'::timestamp without time zone) AND (reminded_count < 3) AND ((last_reminded_at IS NULL) OR (last_reminded_at < '2012-10-10 21:08:05.261483'::timestamp without time zone)) AND ((invite_method)::text = 'email'::text) AND (accept_count = 0))
Total runtime: 11395.970 ms
Run Code Online (Sandbox Code Playgroud)
你可以看到这需要大约11秒.我如何添加索引来优化此查询性能?
只需将@Jim建议的"一切"编入索引并不是一个非常有效的策略.索引确实需要维护和组合许多单个索引的成本比一个定制索引更昂贵(维护和查询).它总是取决于你的完整情况.
对于只读或很少写入的表,索引的成本很低,但对于具有大量写入操作的易失性表,索引的成本很高.另一个缺点是索引禁止HOT更新(仅堆元组).更多相关答案.
如果特定查询的性能很重要,则部分多列索引将是一个很好的策略.专业,但比所有相关列上的单个索引更便宜,更快.经验法则是......
WHERE子句中使用稳定条件(每个查询都相同)来缩小索引的分区.从您的列名称(缺乏信息)来看,这里accept_count = 0似乎是最具选择性(和稳定性)的过滤器,created_at而且last_reminded_at可能会不断变化.也许是这样的:
CREATE INDEX invites_special_idx
ON invites (created_at, last_reminded_at)
WHERE accept_count = 0
AND invite_method = 'email'
AND reminded_count < 3;
Run Code Online (Sandbox Code Playgroud)
排序created_at和last_reminded_at 升序以完美匹配查询 - 这恰好是默认值.这样,系统可以从索引顶部的单次扫描中获取所有相关行.应该很快.
正如我们在您之前的一个问题中所讨论的那样,将表格集中在索引上可能会有额外的帮助.请务必阅读手册CLUSTER.
正如@Craig所提供的,你不能CLUSTER在部分索引上.由于CLUSTER是一次性操作(后期写入操作会降低效果),您可以通过创建完整索引,CLUSTER表格并再次删除索引来规避此限制.喜欢:
CREATE INDEX invites_special_idx2 ON invites (created_at, last_reminded_at);
CLUSTER invites USING invites_special_idx2;
DROP INDEX invites_special_idx2;
Run Code Online (Sandbox Code Playgroud)
CLUSTER 只要没有其他重要查询对数据分布有矛盾的要求,它才有用.
PostgreSQL 9.2有一些新功能可能会使您的查询更快.特别是仅索引扫描(发行说明中的第一项).您可能需要考虑升级.
您应该添加电子邮件、created_at、invite_method、accept_count、remined_count 和 last_remillion 的索引。一般来说,WHERE 语句左侧的任何内容。