postgresql中多个列上的多个索引与单个索引

Posted

技术标签:

【中文标题】postgresql中多个列上的多个索引与单个索引【英文标题】:Multiple indexes vs single index on multiple columns in postgresql 【发布时间】:2017-01-10 20:30:35 【问题描述】:

阅读有关该主题的一些现有帖子,我无法得出任何结论性答案。

我在过去 10 年的 100 个地点拥有某些数据。该表有大约 8 亿行。我需要主要为每个位置生成年度统计数据。有时我还需要生成每月变化统计数据和每小时变化统计数据。我想知道是否应该生成两个索引 - 一个用于位置,另一个用于年份,或者在位置和年份上生成一个索引。我目前的主键是一个序列号(可能我可以使用位置和时间戳作为主键)。

谢谢。

【问题讨论】:

对比类比:***.com/a/24315527/7750999 【参考方案1】:

(location,timestamp) 上的索引应该比 2 个单独的索引更适合您的情况。请注意,列的顺序很重要。

【讨论】:

谢谢。列的顺序如何影响性能? 如果您的搜索条件类似于location="something" AND timestamp BETWEEN something AND something,则可以使用(location,timestamp) 上的索引,而(timestamp,location) 上的索引则不能。 不正确。 where 条件的顺序根本不重要。见这里dba.stackexchange.com/a/115759 @T3rm1 我指的是多列索引定义中的列顺序。这与您的链接完全不同,它与WHERE 子句中的条件顺序有关。在前一种情况下,顺序很重要,在后一种情况下则无关紧要。【参考方案2】:

无论您在关系上创建了多少个索引,在某个查询中只会使用其中一个(哪个取决于查询、统计信息等)。因此,在您的情况下,您不会从创建两个单列索引中获得累积优势。为了从索引中获得最佳性能,我建议在(位置、时间戳)上使用复合索引。

请注意,像 ... WHERE timestamp BETWEEN smth AND smth 这样的查询不会使用上面的索引,而像 ... WHERE location = 'smth'... WHERE location = 'smth' AND timestamp BETWEEN smth AND smth 这样的查询会。这是因为索引中的第一个属性对于搜索和排序至关重要。

别忘了表演

ANALYZE;

创建索引后以收集统计信息。

更新: 正如 @MondKin 在 cmets 中提到的,某些查询实际上可以在同一关系上使用多个索引。例如,使用OR 子句如a = 123 OR b = 456 进行查询(假设两列都有索引)。在这种情况下,postgres 将对两个索引执行位图索引扫描,构建结果位图的并集并将其用于位图堆扫描。在某些情况下,AND 查询可以使用相同的方案,但不会有联合,而是会有一个交集。

【讨论】:

关于only one of them will be used in a certain query 实际上 Postgres 确实有能力使用多个索引来满足单个查询。查看手册中的这一章:postgresql.org/docs/current/indexes-bitmap-scans.html 具体Fortunately, PostgreSQL has the ability to combine multiple indexes 如果我有多列 B 树索引 (location, timestamp),并且我在 where 闭包中使用其中之一。例如where location = smthtimestamp = smth 我创建的索引会起作用吗? 很棒的答案!【参考方案3】:

对于此类情况没有经验法则,我建议您在生产数据库的副本中进行试验,看看哪种方法最适合您:单个多列索引或 2 个单列索引。

Postgres 的一个很好的特性是您可以拥有多个索引并在同一个查询中使用它们。检查this chapter of the docs:

... PostgreSQL 具有组合多个索引的能力... 以处理单索引扫描无法实现的情况 ....

...有时多列索引是最好的,但有时最好创建单独的索引并依赖索引组合功能...

您甚至可以尝试创建单个索引和组合索引,并检查 how big each one is 并确定是否值得同时拥有它们。

您还可以尝试一些事情:

如果您的表太大,请考虑partitioning it。看起来您可以按位置或按日期进行分区。分区将您的表数据拆分为较小的表,从而减少查询需要查找的位置数量。 如果您的数据是根据日期(如交易日期)排列的,请检查BRIN indexes。 如果多个查询将以类似的方式处理您的数据(例如汇总同一时期内的所有交易,请选中 materialized views,这样您只需进行一次代价高昂的汇总。

关于放置多列索引的顺序,首先放置要进行相等操作的列,然后放置要进行范围操作的列,>=<= 操作。

【讨论】:

以上是关于postgresql中多个列上的多个索引与单个索引的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSql jsonb 列上的 GIN 索引未在查询中使用

在 Postgresql 中的多个列上执行 WHERE IN

如何使用 xpath 表达式在 PostgreSQL 中的 XML 列上创建索引?

索引 HSQLDB?

单个索引与多个字段索引

单个节点的多个 Elasticsearch 索引