PostgreSQL:使用主键作为排序键非常慢的ORDER BY
我有这样的模型
具有以下表格大小:
+------------------+-------------+
| Table | Records |
+------------------+-------------+
| JOB | 8k |
| DOCUMENT | 150k |
| TRANSLATION_UNIT | 14,5m |
| TRANSLATION | 18,3m |
+------------------+-------------+
现在下面的查询
select translation.id
from "TRANSLATION" translation
inner join "TRANSLATION_UNIT" unit
on translation.fk_id_translation_unit = unit.id
inner join "DOCUMENT" document
on unit.fk_id_document = document.id
where document.fk_id_job = 11698
order by translation.id asc
limit 50 offset 0
大约需要90秒才能完成。 当我删除ORDER BY和LIMIT子句时,需要19.5秒 。 在执行查询之前, ANALYZE已在所有表上运行。
对于这个特定的查询,这些是满足标准的记录数量:
+------------------+-------------+
| Table | Records |
+------------------+-------------+
| JOB | 1 |
| DOCUMENT | 1200 |
| TRANSLATION_UNIT | 210,000 |
| TRANSLATION | 210,000 |
+------------------+-------------+
查询计划:
没有ORDER BY和LIMIT的修改查询计划在这里。
数据库参数:
PostgreSQL 9.2
shared_buffers = 2048MB
effective_cache_size = 4096MB
work_mem = 32MB
Total memory: 32GB
CPU: Intel Xeon X3470 @ 2.93 GHz, 8MB cache
任何人都可以看到这个查询有什么问题吗?
更新 :对于没有ORDER BY的同一查询的查询计划(但仍然带有LIMIT子句)。
这有点太长了评论。 当您删除order by
子句时,您正在比较苹果和橘子。 如果没有order by
,查询的处理部分只需要提供50行。
按order by
,所有行都需要在排序之前生成,并选择前几个。 如果您order by
limit
条款删除order by
查询需要多长时间?
translation.id
是主键的事实并没有什么不同,因为处理过程需要经过多个联接(筛选结果)。
编辑:
我想知道这将如何与CTE一起首先创建表格,然后再分类并获取结果:
with CTE as (
select translation.id
from "TRANSLATION" translation
inner join "TRANSLATION_UNIT" unit
on translation.fk_id_translation_unit = unit.id
inner join "DOCUMENT" document
on unit.fk_id_document = document.id
where document.fk_id_job = 11698
)
select *
from CTE
order by translation.id asc
limit 50 offset 0;
你有翻译的组合索引(fk_id_translation_unit,id)吗? 在我看来,这将有助于避免需要通过表访问translation.id。
链接地址: http://www.djcxy.com/p/17029.html上一篇: PostgreSQL: Terribly slow ORDER BY with primary key as the ordering key