4

我有一个相当复杂的查询,其中包括一个ORDER BY和一个LIMIT子句。当ORDER BY使用主键时,查询时间不到 5 毫秒。但是,如果我将查询更改ORDER BY为由不同的列(类型FLOAT)完成,响应时间会膨胀到超过 50 秒(高四个数量级!)。

现在,我认为问题是按主键排序的查询执行索引扫描,而按浮点列排序的查询执行顺序扫描并需要在最后进行排序。

我认为只需在 float 列上添加索引就足以让 Postgresql 以更智能的方式计划此查询。显然我错了。我可能错过了什么?

编辑:EXPLAIN ANALYZE在发布问题之前确实运行过。因此,我的假设不仅仅是一个疯狂的猜测;但是,由于EXPLAIN ANALYZE运行的输出超过 30 行,因此尚不清楚为什么一个查询使用索引而另一个查询必须对所有行进行排序。

4

3 回答 3

4
  1. 对查询运行解释分析 - 这样您就不必猜测会发生什么。
  2. 要优化查询,您通常必须阅读解释分析输出、查询,然后找出最佳行动方案。有时 - 它正在添加索引,有时 - 重写查询。但无法判断哪个最适合您的情况,因为我们看不到解释或查询。
于 2013-02-06T17:13:07.097 回答
2

在没有看到查询的情况下很难破译正在发生的事情。我的猜测是查询计划能够基于具有主键的表进行连接,从而使数据保持正确的顺序。然后查询计划基本上是获取一行,在其他表中查找值,对它们进行处理,然后按顺序返回值。处理尽可能地进行limit

当您将其替换为 中的另一列时order by,必须处理所有行。这些被排序并返回。它可能是基础表的大小,也可能是结果集的大小,导致处理时间更长。但是,根本原因是需要生成所有行。

于 2013-02-06T17:13:35.490 回答
0

对于返回许多行的查询,数据库使用非覆盖索引是不常见的。查表(从索引到表数据)的成本太高。将改为使用表扫描。

例如,

select name from people where name > 'N' order by birthdate

数据库会使用索引(birthday)吗?从好的方面来说,行将以正确的顺序返回。不利的一面是,每一行都需要对该name列进行表查找。第二个要贵得多,因此不会使用索引。

上的索引(birthday, name)是不同的。它包括名称,因此不需要查找表。数据库可以使用索引以正确的顺序快速返回行。

包含查询所需的所有列的索引称为覆盖索引。确保您的索引包含查询使用的所有列,然后重试。

于 2013-02-06T17:10:57.817 回答