【问题标题】:Postgresql order by and limitPostgresql 排序和限制
【发布时间】:2012-09-28 14:45:40
【问题描述】:

我有一个表 R,想根据 z 列从中选择 3 个前任或后继。我在 z 列上有一个 btree 索引。

SELECT key, z, x, y FROM R
    WHERE z <= some_value
    ORDER BY z DESC 
    LIMIT 3

立即检索前辈,但是

SELECT key, z, x, y FROM R
    WHERE z >= some_value
    ORDER BY z ASC
    LIMIT 3

对于检索下一个条目是无用的,因为它开始扫描所有具有 z >= some_value 的行。 Explain 对如何满足查询给出了相同的解释。 为什么会这样?我该怎么办?

编辑: 实际上有两个索引,一个升序,一个降序。 解释上面的两个查询说: “限制(成本=0.00..31.91 行=3 宽度=20)” “ -> 在 r 上使用 zreverse 向后索引扫描(成本=0.00..17727815.24 行=1666667 宽度=20)” " 过滤器:(z >= some_value")

【问题讨论】:

  • 您能否向我们发布这两个查询的 EXPLAIN 输出?有关如何使用此命令,请参阅 postgresql.org/docs/current/static/using-explain.html
  • 你试过explain analyze而不是explain吗?
  • 问题在于用于计算 some_value 的简单函数,为了清楚起见,这里省略了...它被定义为 volatile 导致它为每一行单独计算。

标签: sql postgresql


【解决方案1】:

嗯……

WHERE 子句中使用的一些值是由一个简单的函数计算的,该函数(错误地)定义为 VOLATILE。将其更改为 STABLE 解决了这个问题。

【讨论】:

  • 很高兴知道这一点:根据postgresql.org/docs/current/static/xfunc-volatility.html,优化器不对从标记为 volatile 的函数返回的值做任何假设,并为每一行执行一次此函数。如果标记为稳定,优化器知道返回的值对于相同的输入将是相同的,并且可以优化函数的执行——例如索引扫描。
【解决方案2】:

z 上的索引是“普通”btree 索引,没有指定其他内容吗?或者它是以“降序”顺序创建的,即作为

create index <name> on R(z) desc;

?

很可能将相反的顺序索引添加到您拥有的索引上可能会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-09
    • 2018-08-19
    • 2014-04-27
    • 2020-02-29
    • 2014-12-13
    • 1970-01-01
    • 2017-05-23
    相关资源
    最近更新 更多