在一个应用程序中,我需要查询Postgres数据库,我希望结果集中有数十甚至数亿行。我可能每天进行一次查询,甚至更频繁。查询本身相对简单,但可能涉及一些JOIN。
我的问题是:Postgres在避免为结果集的每一行搜索磁盘方面有多聪明?考虑到寻求硬盘所需的时间,这可能非常昂贵。
如果这不是问题,Postgres如何避免它?它如何知道如何在磁盘上布置数据,以便能够以有效的方式流出来响应此查询?
答案 0 :(得分:2)
当PostgreSQL analyzes your data时,查询计划程序计算并使用的统计信息之一是字段或索引中值的排序与磁盘上的顺序之间的correlation。
物理行排序与列值的逻辑排序之间的统计相关性。范围从-1到+1。当该值接近-1或+1时,由于减少了对磁盘的随机访问,因此估计列上的索引扫描比接近零时更便宜。 (如果列数据类型没有<运算符,则此列为NULL。)
index cost estimation functions还会计算相关性:
indexCorrelation应设置为索引顺序和表顺序之间的相关性(介于-1.0和1.0之间)。这用于调整从父表中获取行的成本的估计值。
我不确定,但我认为规划人员在确定是否可以通过执行表格以较低的成本完成从表中读取的行数时,会使用各种可能计划的相关值扫描,使用顺序io(可能加入同一个表的另一个并发扫描),过滤所需的行,或索引扫描,以及其产生的搜索。
PostgreSQL不会根据任何特定键对表进行排序,但可以使用CLUSTER命令定期在特定的索引顺序中重新创建表(这将很慢,每行有一个磁盘搜索,如果数据到集群与索引值顺序的相关性很低。
PostgreSQL能够有效地收集一组需要检索的磁盘块,然后以物理顺序获取它们以减少搜索。它通过Bitmap Scans实现。 Release Notes for 8.1说:
即使使用单个索引,位图扫描也很有用,因为它们可以减少所需的随机访问量;位图索引扫描对于检索完整表的相当大部分是有效的,而普通索引扫描则不是。
编辑:我想提及planner cost contants seq_page_cost
和random_page_cost
,它们告知规划人员执行磁盘页面获取的相对成本,这是一系列连续提取的一部分,与非顺序获取的磁盘页面。