2

我有 PostgreSQL 表,每个表都有数百万条记录和一百多个字段。
其中之一是日期字段,我们在查询中对此进行过滤。为这个日期字段创建索引提高了读取小范围日期的查询的性能,但在大范围的日期中,性能下降了......

我必须优先考虑其中一个吗?可以在不减少大范围查询的情况下提高小范围的性能吗?

4

4 回答 4

3

仅使用索引中的信息无法回答 PostgreSQL 中的查询。从正在执行的查询的角度来看,该行是否可见,都存储在主行本身中。因此,当您向某事物添加索引并执行使用它的查询时,涉及两个步骤:

  • 导航索引以确定使用了哪些数据块
  • 检索这些块并返回与查询匹配的行

因此,使用索引回答查询可能需要比直接访问数据块并获取行更长的时间。发生这种情况的最常见情况是,如果您实际上正在获取大部分数据。通常,如果使用了超过 20% 的表,则认为仅按顺序访问它会很快。有时规划者认为不到 20% 会被访问,所以首选索引,但事实并非如此;这是添加索引会减慢查询速度的一种方式。根据您的描述,这可能是您所看到的情况——如果大范围涉及的表比优化器估计的要多,则使用索引可能会导致速度下降。

为了解决这个问题,数据库收集每个表中每一列的统计信息,以确定特定的 WHERE 条件是否具有足够的选择性以使用索引。这个想法是你需要通过不读取整个表来保存这么多块,在它上面添加索引 I/O 仍然是一个净赢。

这种计算可能会出错,因此在某些情况下,您最终会执行比直接读取表更多的 I/O。如果您使用 EXPLAIN ANALYZE 运行查询,则会显示其中大多数的原因。如果“预期”值与“实际”数字非常不同,这可能表明优化器对表的统计信息不正确。另一种可能性是优化器在查询的选择性方面犯了一个错误——它认为它只会返回少量的行,但实际上它返回了大部分的表。再次,更好的统计数据是开始工作的正常方式。如果您使用的是 PostgreSQL 8.3 或更早版本,默认情况下收集的统计信息量非常低。

一些工作负载最终也会调整 random_page_cost 可调参数,该可调参数控制此索引与表扫描权衡发生的位置。不过,这只是在检查统计信息后才需要考虑的事情。请参阅Tuning Your PostgreSQL Server以了解您可以在此处调整的几项内容。

于 2011-05-25T22:33:35.530 回答
0

为这个日期字段创建索引提高了读取小范围日期的查询的性能,但在大范围的日期中,性能下降了......

尝试使用该索引对表进行聚类。性能下降可能是由于整个表在大范围内打开。如果是这样,沿着该索引对表进行聚类将导致更少的磁盘查找。

于 2011-05-25T07:53:53.987 回答
0

两个建议:

1)调查table inheritance时间序列数据的使用。例如,每月创建一个子表,然后对每个表的日期进行 INDEX。PostgreSQL 足够聪明,只能index_scan在日期范围内具有实际数据的子表上执行 's。一旦子表因为是新月份而被“密封”,CLUSTER请在表上运行以按日期对数据进行排序。

2)看看创建一堆INDEX使用WHERE子句的's。

建议 #1 将成为长期的赢家,但需要一些工作来设置(但将永远扩展/运行),但如果您关心扫描的日期范围有限,建议 #2 可能是一个快速的临时修复。请记住,您只能在'子句中使用IMMUTABLE函数。INDEXWHERE

CREATE INDEX tbl_date_2011_05_idx ON tbl(date) WHERE date >= '2011-05-01' AND date <= '2011-06-01';
于 2011-05-25T18:28:19.293 回答
0

我会尝试几件事:

  • 增加数据库缓存参数
  • 在该日期字段上添加索引
  • 重新设计/修改应用程序以使用更小的范围(尽管这个建议似乎很明显,但通常首先被丢弃)
于 2011-05-25T06:36:59.530 回答