【问题标题】:Postgres ignoring clustered index on date queryPostgres忽略日期查询的聚集索引
【发布时间】:2013-12-23 00:14:32
【问题描述】:

我有一个大表,我定期运行诸如 select date_att > date '2001-01-01' 之类的查询。我试图通过在 date_att 上对表进行聚类来提高这些查询的速度,但是当我通过解释分析运行这些查询时,它仍然选择按顺序扫描表,即使是像 SELECT date_att from table where date_att > date 这样简单的查询'2001-01-01'。为什么会这样?我知道,由于查询返回表的大部分,优化器将忽略索引,但由于该表是由该属性聚集的,它不应该能够真正快速地通过表进行二进制搜索到日期> '2001-01-01' 然后返回所有结果?这个查询仍然需要和没有聚类一样多的时间。

【问题讨论】:

  • 你能显示你的表和索引定义吗,你说你在日期列上有一个聚集索引,我很困惑,然后你参考“顺序扫描表”,表扫描聚集索引扫描。
  • 感谢您的快速响应- 表定义是:CREATE TABLE test(dummy_primary_key integer, date_att date, primary key(dummy_primary_key)); 然后我在 date_att 上创建一个索引并使用以下命令对其进行集群:CREATE INDEX dateindex on test(date_att); CLUSTER test using dateindex; 然后,运行 SELECT date_att FROM test WHERE date_att > date '2001-01-01' 仍然需要10 秒。测试包含大量数据,查询返回大约一半的数据。根据我对聚集索引的理解,这应该很快,但仍然很慢。
  • 嗯,恐怕这对我来说是个谜。我对Postgresql知之甚少,不知道分析器是如何工作的,有趣的是,对于您发布的表定义,使用了索引,一旦将其他列添加到表中,索引就不再使用,甚至尽管查询中未引用其他列。 sqlfiddle.com/#!15/94380/1
  • 奇怪...我只是在 psql 命令行上尝试了相同的操作,无论定义是什么,它都会进行 seqscans...无论如何谢谢!
  • 请从explain analyze发布执行计划(或上传到explain.depesz.com)。不要不要将此作为评论发布,编辑您的问题。您可能还想阅读以下内容:wiki.postgresql.org/wiki/Slow_Query_Questions

标签: sql postgresql indexing clustered-index


【解决方案1】:

您似乎混淆了两个概念:

PostgreSQL 表集群

根据 PostgreSQL 中的索引对表进行聚类会将表行的顺序(存储在堆表中)与聚类时索引中的顺序对齐。来自文档:

聚类是一次性操作:当表随后 更新后,更改不会聚集。 http://www.postgresql.org/docs/9.3/static/sql-cluster.html

集群可能(通常)提高范围查询的查询速度,因为选定的行存储在堆表附近巧合。没有什么可以保证这个订单!因此优化器不能假设它是真的。

例如如果您插入一个满足您的 where 子句的新行,它可能会插入到表中的任何位置 - 例如其中存储 1990 年的行。因此,这个假设不成立:

但是由于该表是由该属性聚集的,它是否应该能够真正快速地对表进行二进制搜索到 date > '2001-01-01' 并返回之后的所有结果?

这让我们想到了你提到的另一个概念:

聚集索引

这是完全不同的东西,PostgreSQL 根本不支持,但许多其他数据库(SQL Server、带有 InnoDB 的 MySQL 以及称为“索引组织表”的 Oracle)都支持。

在这种情况下,表数据本身存储在索引结构中——没有单独的堆结构!由于它是一个索引,因此每个insert/update/delete 的顺序也保持不变。因此,您的假设将成立,实际上我希望上述数据库的行为与您预期的一样(鉴于 date 列是聚类键!)。

希望澄清一下。

【讨论】:

  • @josh-hull 我已经手动添加了您建议的编辑,因为它已经被人群拒绝了。愚蠢的系统。也可以在这里查看:meta.stackexchange.com/questions/185472/…
  • 那么在 PostgreSQL 中集群表的用例是什么?自过去 12 小时以来,我一直在阅读这个主题,现在我完全糊涂了。
  • @KamilLatosinski 我从来没有将 PostgreSQL 集群用于任何事情。这是一个旧功能,我怀疑它是否适用于更现代的功能(如仅索引扫描)。我想现在它的用途仅限于极少数的极端情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 2011-06-15
  • 2023-03-17
相关资源
最近更新 更多