postgresql中多列上的多个索引与单个索引
Multiple indexes vs single index on multiple columns in postgresql
我无法通过阅读有关此主题的一些现有帖子得出任何结论性答案。
我有过去 10 年在 100 个地点的某些数据。 table 有大约 8 亿行。我需要主要为每个位置生成年度统计数据。有时我还需要生成每月变化统计数据和每小时变化统计数据。我想知道我是否应该生成两个索引 - 一个用于位置,另一个用于年份,或者为位置和年份生成一个索引。我的主键目前是一个序列号(可能我可以使用位置和时间戳作为主键)。
谢谢。
(location,timestamp) 上的索引应该比 2 个单独的索引更适合您的情况。请注意,列的顺序很重要。
不管你在关系上创建了多少个索引,在某个查询中只会使用其中一个(哪个取决于查询、统计等)。因此,在您的情况下,您不会从创建两个单列索引中获得累积优势。为了从索引中获得最大性能,我建议在 (location, timestamp) 上使用复合索引。
请注意,像 ... WHERE timestamp BETWEEN smth AND smth
这样的查询不会使用上面的索引,而像 ... WHERE location = 'smth'
或 ... WHERE location = 'smth' AND timestamp BETWEEN smth AND smth
这样的查询会。这是因为索引中的第一个属性对于搜索和排序至关重要。
别忘了表演
ANALYZE;
创建索引以收集统计信息后。
更新:
正如评论中提到的 @MondKin 某些查询实际上可以在同一关系上使用多个索引。例如,使用 OR
子句查询,如 a = 123 OR b = 456
(假设两列都有索引)。在这种情况下,postgres 将对两个索引执行位图索引扫描,构建结果位图的并集并将其用于位图堆扫描。在某些情况下,相同的方案可用于 AND
查询,但不是并集,而是交集。
对于此类情况没有经验法则,我建议您在生产数据库的副本中进行试验,看看哪种方法最适合您:单个多列索引或 2 个单列索引。
Postgres 的一个不错的特性是您可以拥有多个索引并在同一个查询中使用它们。检查 this chapter of the docs:
... PostgreSQL has the ability to combine multiple indexes ... to handle cases that cannot be implemented by single index scans ....
... Sometimes multicolumn indexes are best, but sometimes it's better to create separate indexes and rely on the index-combination feature ...
您甚至可以尝试创建单独索引和组合索引,然后检查 how big each one is 并确定是否值得同时拥有它们。
您还可以尝试的一些事情:
- 如果您的 table 太大,请考虑 partitioning it。看起来您可以按位置或按日期进行分区。分区将 table 的数据拆分为更小的 table,从而减少了查询需要查看的位置。
- 如果您的数据是根据日期(如交易日期)排列的,请检查 BRIN indexes。
- 如果多个查询将以类似的方式处理您的数据(例如聚合同一时期内的所有交易,请选中 materialized views,这样您只需执行一次这些昂贵的聚合。
关于放置多列索引的顺序,首先放置要对其进行相等操作的列,然后放置具有范围的列,>=
或 <=
操作.
我无法通过阅读有关此主题的一些现有帖子得出任何结论性答案。
我有过去 10 年在 100 个地点的某些数据。 table 有大约 8 亿行。我需要主要为每个位置生成年度统计数据。有时我还需要生成每月变化统计数据和每小时变化统计数据。我想知道我是否应该生成两个索引 - 一个用于位置,另一个用于年份,或者为位置和年份生成一个索引。我的主键目前是一个序列号(可能我可以使用位置和时间戳作为主键)。
谢谢。
(location,timestamp) 上的索引应该比 2 个单独的索引更适合您的情况。请注意,列的顺序很重要。
不管你在关系上创建了多少个索引,在某个查询中只会使用其中一个(哪个取决于查询、统计等)。因此,在您的情况下,您不会从创建两个单列索引中获得累积优势。为了从索引中获得最大性能,我建议在 (location, timestamp) 上使用复合索引。
请注意,像 ... WHERE timestamp BETWEEN smth AND smth
这样的查询不会使用上面的索引,而像 ... WHERE location = 'smth'
或 ... WHERE location = 'smth' AND timestamp BETWEEN smth AND smth
这样的查询会。这是因为索引中的第一个属性对于搜索和排序至关重要。
别忘了表演
ANALYZE;
创建索引以收集统计信息后。
更新:
正如评论中提到的 @MondKin 某些查询实际上可以在同一关系上使用多个索引。例如,使用 OR
子句查询,如 a = 123 OR b = 456
(假设两列都有索引)。在这种情况下,postgres 将对两个索引执行位图索引扫描,构建结果位图的并集并将其用于位图堆扫描。在某些情况下,相同的方案可用于 AND
查询,但不是并集,而是交集。
对于此类情况没有经验法则,我建议您在生产数据库的副本中进行试验,看看哪种方法最适合您:单个多列索引或 2 个单列索引。
Postgres 的一个不错的特性是您可以拥有多个索引并在同一个查询中使用它们。检查 this chapter of the docs:
... PostgreSQL has the ability to combine multiple indexes ... to handle cases that cannot be implemented by single index scans ....
... Sometimes multicolumn indexes are best, but sometimes it's better to create separate indexes and rely on the index-combination feature ...
您甚至可以尝试创建单独索引和组合索引,然后检查 how big each one is 并确定是否值得同时拥有它们。
您还可以尝试的一些事情:
- 如果您的 table 太大,请考虑 partitioning it。看起来您可以按位置或按日期进行分区。分区将 table 的数据拆分为更小的 table,从而减少了查询需要查看的位置。
- 如果您的数据是根据日期(如交易日期)排列的,请检查 BRIN indexes。
- 如果多个查询将以类似的方式处理您的数据(例如聚合同一时期内的所有交易,请选中 materialized views,这样您只需执行一次这些昂贵的聚合。
关于放置多列索引的顺序,首先放置要对其进行相等操作的列,然后放置具有范围的列,>=
或 <=
操作.