没有 WHERE 的 PostgreSQL 查询仅 ORDER BY 和 LIMIT 不使用索引

2023-12-23

我有一个表,其中包含 BIGSERIAL 类型的“id”列。我也有这一列的索引(降序排序、BTREE、唯一)。

我经常需要从包含数百万条目的表中检索最后 10、20、30 个条目,如下所示:

SELECT * FROM table ORDER BY id DESC LIMIT 10

我本以为这是一个非常清楚的情况:这个特定字段有一个索引,排序顺序匹配,与整个表中的数百万个条目相比,我只需要 10 个条目,这个查询肯定使用索引扫描。

但它不会对整个表进行顺序扫描。

我尝试深入挖掘,没有发现任何异常。 Postgres 文档位于https://www.postgresql.org/docs/9.6/static/indexes-ordering.html https://www.postgresql.org/docs/9.6/static/indexes-ordering.html says:

一个重要的特殊情况是 ORDER BY 与 LIMIT n 的组合: 显式排序必须处理所有数据才能识别第一个 n 行,但如果存在与 ORDER BY 匹配的索引,则前 n 可以直接检索行,而根本不需要扫描其余部分。

但还是不行。有人给我指点吗?也许我只是不再只见树木不见阿甘了……:-(


好吧,大声说出来并试图收集更多信息来提出我的问题显然让我再次看到了阿甘,我发现了真正的问题。我上面提到的文档的下面是这句话:

以升序存储且空值在前的索引可以满足以下任一条件 ORDER BY x ASC NULLS FIRST 或 ORDER BY x DESC NULLS LAST 取决于 扫描的方向。

这就是问题所在。我在索引中指定了排序顺序,但忽略了 NULLS FIRST 与 LAST。

如果您没有在查询中明确提及,Postgres 默认值为 NULLS FIRST。所以 Postgres 发现的是组合 ORDER BY DESC NULLS FIRST ,它没有被我的索引覆盖。 SORT ORDER 和 NULLS 的组合才是重要的。

2种可能的解决方案:

  • 在查询中相应地提及 NULLS FIRST/LAST 以便它与索引匹配
  • ...或者将索引更改为 NULLS FIRST (这就是我所做的)

现在 Postgres 正在执行适当的索引扫描,并且在查询期间仅触及 10 个元素,而不是全部。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

没有 WHERE 的 PostgreSQL 查询仅 ORDER BY 和 LIMIT 不使用索引 的相关文章

  • 仅从数据库获取我想要的数据但保留结构

    我正在尝试在 powerbi 上执行此操作 但我想这只是基本的 SQL 我想将我的数据导入到 powerBi 中 但使用一些 id 对其进行过滤 我们以这个例子为例 我与一些公司有数据库 表1 每个公司都有建筑物 表2 每个建筑物有员工 表
  • Mysql为简单频繁查询创建排序索引性能

    我正在处理一个包含大约 400 万条消息条目的 mysql 表 并尝试根据时间戳选择最新的 50 条消息 另一个要求是返回的消息不以固定前缀开头 问题是单个查询大约占用 25 的 cpu 并且最多需要 1 5 秒 该查询经常由多个客户端执行
  • 为什么 sql 字段名称中不应该包含逗号?

    人们一直告诉我列名中不应包含空格 我只是想知道 这是为什么 这是我为学校创建的一些数据库表遇到的问题 字段名称包括 Preble 和 Darke 相反 它们需要是 普雷布尔县 俄亥俄州 和 达克县 俄亥俄州 如果它们是行名称 我只需创建一个
  • 如何在没有 EF 的 ASP.NET MVC 中使用普通 sql?

    我有一个使用 linq to sql 的类 如何在 ASP NET MVC 3 中使用普通 sql 而不使用 EF 来实现相同的功能 public ActionResult Index var List from c in db OFFIC
  • 返回行位置 - Postgres

    我返回一个带有位置的表 select from select row number over as position from organization result where data1 Hello 返回这个 这是正确的 data1 H
  • 显示过去 7 天 PHP 的结果

    我想做的是显示过去 30 天的文章 但我现有的代码不断给我一个 mysql fetch assoc 错误 然后追溯到我的查询 这是代码 sql mysql query SELECT FROM table WHERE DATE datetim
  • 从备份恢复 PostgreSQL 数据库,没有外键约束问题

    我有一个包含大约 85 个以上表的 postgresql 数据库 我定期使用pg dump 通过 php pgadmin 在复制模式下 备份文件的大小几乎为 10 12 MB 现在我面临的问题是 每当我尝试恢复数据库时 都会出现外键约束问题
  • 在同一个表上组合两个 SQL SELECT 语句

    我想结合这两个 SQL 查询 SELECT FROM Contracts WHERE productType RINsell AND clearTime IS NULL AND holdTime IS NOT NULL ORDER BY g
  • 获取查询的行号

    我有一个查询将返回一行 当表排序时 有什么方法可以找到我正在查询的行的行索引吗 我试过了rowid但当我期待第 7 行时却得到了 582 Eg CategoryID Name I9GDS720K4 CatA LPQTOR25XR CatB
  • 具有 LINQ 支持的最完整的 ORM?

    我正在寻找一个提供完整或接近完整的 LINQ 支持的 ORM LINQ 到 SQL 支持 LINQ 内部的所有内容 Contains Math Log 等 在不创建新数据上下文的情况下无法预先加载关系属性 ADO NET 实体框架 糟糕的
  • 在 postgresql 9.4 或 9.5 中查询 json 对象的嵌套数组中的元素

    studentID 1 StudentName jhon Data schoolname school1 enrolmentInfo year 2015 info courseID csc213 school IT enrollmentda
  • POSTGRESQL:如何在现有表上添加包含数据的新列

    我是 postgres 和 sql 脚本的新手 所以请耐心等待 我想要做的是在现有表上添加包含数据的现有列 现有表的示例 NAME AGE Adam 25 Tim 30 现在我想添加一个新列 ADDRESS 其中包含 Adam 和 Tim
  • 操作错误:游标“_django_curs_”不存在

    我们有一个由 django postgresql 和 heroku 提供支持的在线商店 Web 应用程序 对于特定的活动 您可以将活动视为要购买的产品 我们已成功售出 10 000 份以上的副本 然而 根据我们的 Sentry 报告 我们的
  • Postgres、更新和锁定顺序

    我正在研究 Postgres 9 2 有 2 个更新 每个更新都有自己的事务 一个看起来像 UPDATE foo SET a 1 WHERE b IN 1 2 3 4 另一个也类似 UPDATE foo SET a 2 WHERE b IN
  • 从 PDO 准备好的语句中获取原始 SQL 查询字符串

    在准备好的语句上调用 PDOStatement execute 时 有没有办法让原始 SQL 字符串执行 出于调试目的 这将非常有用 我假设您的意思是您想要最终的 SQL 查询 并将参数值插入其中 我知道这对于调试很有用 但这不是准备好的语
  • pq:函数unnest(未知)不是唯一的

    以下代码工作正常 但我想将 array a b c d e 定义为变量 rows err db Query select colname from SELECT date unnest array a b c d e AS colname
  • Oracle:如果表存在

    我正在为 Oracle 数据库编写一些迁移脚本 并希望 Oracle 有类似于 MySQL 的东西IF EXISTS构造 具体来说 每当我想删除 MySQL 中的表时 我都会执行类似的操作 DROP TABLE IF EXISTS tabl
  • 在存储过程结束时显式删除本地临时表有什么好处?

    考虑以下伪 T SQL 代码 由存储过程执行 CREATE TABLE localTable
  • 通过将行旋转为动态数量的列来在 MySQL 中创建摘要视图

    我在 MySQL 中有一个表 其中包含以下字段 id company name year state 同一客户和年份有多行 以下是数据示例 id company name year state 1 companyA 2008 1 2 com
  • 从一个sql服务器选择到另一个sql服务器?

    我想将一台服务器 Data Old S1 中的一个表 T1 在 DB1 中 中的数据选择到另一台服务器 Data Latest S2 中的另一个表 T2 在 DB2 中 中的数据 我怎样才能做到这一点 请注意服务器的命名方式 查询也应该考虑

随机推荐