我有PostgreSQL表,每个表有数百万条记录,超过100个字段 其中一个是日期字段,我们在查询中对此进行过滤。为此日期字段创建索引可以提高读取小范围日期的查询的性能,但是在大范围的日期中,性能会下降......
我必须优先考虑另一个吗?在不减少大范围查询的情况下,可以改善小范围内的性能吗?
答案 0 :(得分:3)
使用索引中的信息无法回答PostgreSQL中的查询。从正在执行的查询的角度来看,该行是否可见,存储在主行本身中。因此,当您向某个内容添加索引并执行使用它的查询时,涉及两个步骤:
因此,使用索引回答查询可能需要更长时间,而不是直接转到数据块并获取行。发生这种情况的最常见情况是,如果您实际抓取了大部分数据。通常,如果使用超过20%的表,则只需按顺序访问它即可。有时计划者认为不到20%会被访问,所以索引是首选,但事实并非如此;添加索引的一种方法可能会减慢查询速度。根据您的描述,这可能是您所看到的情况 - 如果大范围触及的表格比优化程序估计的更多,则使用索引可能会导致净减速。
为了解决这个问题,数据库收集有关每个表中每列的统计信息,以确定特定WHERE条件是否足够有选择性以使用索引。这个想法是你需要通过不读取整个表来保存这么多块,因为在它之上添加索引I / O仍然是一个净赢。
这种计算可能会出错,因此在一些情况下,您最终会比直接读取表格时执行更多的I / O操作。如果使用EXPLAIN ANALYZE运行查询,则会显示大多数原因。如果“预期”值与“实际”数字非常不同,则可能表明优化器在表格上有错误的统计信息。另一种可能性是优化器只是错误地判断查询的选择性 - 它认为它只返回少量行,但它实际上返回了大部分表。在这里,更好的统计数据是开始研究的常用方法。如果你使用PostgreSQL 8.3或更早版本,默认情况下收集的统计数据量非常低。
某些工作负载最终也会调整random_page_cost可调参数,从而控制此索引与表扫描权衡发生的位置。在检查统计信息之后,这只是需要考虑的事项。有关您可以在此处调整的几项内容的介绍,请参阅Tuning Your PostgreSQL Server。
答案 1 :(得分:0)
我会尝试几件事:
答案 2 :(得分:0)
为此日期字段创建索引可以提高读取小范围日期的查询的性能,但是在大范围的日期中,性能会下降......
使用该索引尝试clustering您的表格。性能下降可能是由于整个表在大范围内打开。如果是这样,沿着该索引对表进行聚类将导致更少的磁盘搜索。
答案 3 :(得分:0)
两个建议:
1)调查table inheritance
对时间序列数据的使用。例如,每月创建一个子表,然后在每个表上INDEX日期。 PostgreSQL非常聪明,只能在具有日期范围内实际数据的子表上执行index_scan
。一旦子表被“密封”,因为它是新的月份,请在表格上运行CLUSTER
以按日期对数据进行排序。
2)看看创建一堆使用INDEX
子句的WHERE
。
建议#1将成为长期的赢家,但需要一些工作来设置(但会永久扩展/运行),但如果你有一个有限的日期范围你可以快速临时修复建议#2关于扫描。请注意,您只能在IMMUTABLE
的{{1}}条款中使用INDEX
个函数。
WHERE