Sql 带限制1的索引顺序

Sql 带限制1的索引顺序,sql,postgresql,indexing,sql-order-by,postgresql-performance,Sql,Postgresql,Indexing,Sql Order By,Postgresql Performance,我正在尝试获取表中最近的行。我在处创建了一个简单的时间戳,并对其进行了索引。当我在DESC LIMIT 1查询创建的订单时,所花费的时间远远超出我的想象(在我的机器上,36k行大约50毫秒) 解释ing声称它使用向后索引扫描,但我确认将索引更改为(在DESC创建)不会改变查询计划器中简单索引扫描的成本 我如何优化这个用例 运行postgresql9.2.4 编辑: 假设我们处理的是一个大表,a可能会有所帮助: CREATE INDEX tbl_created_recently_idx ON tb

我正在尝试获取表中最近的行。我在处创建了一个简单的时间戳
,并对其进行了索引。当我在DESC LIMIT 1查询创建的订单时,所花费的时间远远超出我的想象(在我的机器上,36k行大约50毫秒)

解释ing声称它使用向后索引扫描,但我确认将索引更改为
(在DESC创建)
不会改变查询计划器中简单索引扫描的成本

我如何优化这个用例

运行postgresql
9.2.4

编辑:
假设我们处理的是一个大表,a可能会有所帮助:

CREATE INDEX tbl_created_recently_idx ON tbl (created_at DESC)
WHERE created_at > '2013-09-15 0:0'::timestamp;
正如你们已经发现的:下降或上升在这里几乎不重要。Postgres可以以几乎相同的速度向后扫描(多列索引除外)

要使用此索引的查询:

SELECT * FROM tbl
WHERE  created_at > '2013-09-15 0:0'::timestamp -- matches index
ORDER  BY created_at DESC
LIMIT  1;
这里的要点是使索引小得多,因此它应该更容易缓存和维护

  • 您需要选择一个时间戳,该时间戳必须小于最近的时间戳
  • 您应该不时重新创建索引以切断旧数据
  • 条件必须是不可变的
  • 因此,一次性效应随着时间的推移而恶化。特定问题是硬编码条件:

    WHERE created_at > '2013-09-15 0:0'::timestamp
    
    自动化 您可以随时手动更新索引和查询。或者,您可以借助以下功能实现自动化:

    CREATE OR REPLACE FUNCTION f_min_ts()
      RETURNS timestamp LANGUAGE sql IMMUTABLE AS
    $$SELECT '2013-09-15 0:0'::timestamp$$
    
    索引:

    CREATE INDEX tbl_created_recently_idx ON tbl (created_at DESC);
    WHERE created_at > f_min_ts();
    
    查询:

    SELECT * FROM tbl
    WHERE  created_at > f_min_ts()
    ORDER  BY created_at DESC
    LIMIT  1;
    
    使用cron作业或一些基于触发器的事件自动执行重新创建。您的查询现在可以保持不变。但是,更改后,您需要以任何方式使用此函数重新创建所有索引。只需删除并创建每一个

    第一。。 。。。测试你是否真的遇到了瓶颈

    尝试是否简单的
    删除索引;创建索引…
    执行此任务。那么你的索引可能已经膨胀了。您的自动真空设置可能已关闭

    或者尝试
    VACUUM FULL analysis
    ,使整个表和索引处于原始状态,然后再次检查


    其他选项包括和,具体取决于您从表中实际检索到的内容。

    您可以将解释的结果添加到问题中吗?谢谢,在发布问题之前,我已经完成了抽真空、重新编制索引和重新创建索引的步骤。这是可行的,现在我只需要记住维护它。部分索引条件是否在创建过程中进行了评估?
    REINDEX
    是否再次重新评估条件?(那太好了)@farnoy:索引的条件必须是
    不可变的
    。也就是说,研究生可以放心地认为结果永远不会改变。如果更改这样一个函数,则需要使用它重新创建所有索引。
    SELECT * FROM tbl
    WHERE  created_at > f_min_ts()
    ORDER  BY created_at DESC
    LIMIT  1;