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 BYLIMIT子句时,需要19.5秒 。 在执行查询之前, ANALYZE已在所有表上运行。

对于这个特定的查询,这些是满足标准的记录数量:

+------------------+-------------+
| Table            |     Records |
+------------------+-------------+
| JOB              |          1  |
| DOCUMENT         |       1200  |
| TRANSLATION_UNIT |    210,000  |
| TRANSLATION      |    210,000  |
+------------------+-------------+

查询计划:

在这里输入图像描述

没有ORDER BYLIMIT的修改查询计划在这里。

数据库参数:

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

下一篇: Fastest way to copy one array list to another