假设数据分布没有变化,对于同一个查询,只有数据集被放大一次,所用的时间也会变成1次?如果数据分布没有改变,理论上是否会改变查询计划?
答案 0 :(得分:2)
是的,即使数据完全是静态的,查询计划仍可能会更改,但可能不会。
autovaccum守护程序将ANALYZE
您的表并生成新的统计信息。这通常只在它们发生变化时发生,但可能由于其他原因(环绕预防真空等)而发生。
统计信息包括随机抽样,用于收集直方图的常用值。随机,每次结果可能会有所不同。
为了减少静态数据集的计划转换的可能性,您可能希望增加表的列上的统计目标并重新分析。不要设置得太高,因为查询计划程序在做出计划决策时必须读取这些直方图,而更大的直方图意味着更多的计划时间。
如果您的桌子持续增长但分布没有变化,那么您希望计划员在各个点改变计划。通过顺序扫描几乎可以最好地访问1000行表。索引扫描会浪费时间和精力。您当然不希望顺序扫描百万行表,除非您正在检索大多数行。因此,规划人员应该 - 并且确实 - 不仅根据数据分布调整其决策,而且还根据整体行数进行调整。
答案 1 :(得分:1)
这是一个例子。您在一个页面和索引上有记录。考虑一下查询:
select t.*
from table t
where col = x;
并且,假设您有col
的索引。使用一条记录,最快的方法是简单地读取记录并检查where
子句。您可以在页面上有200条记录,因此查询的选择性可能小于1%。
SQL优化器在选择算法时考虑的一个关键考虑因素是预期的页面读取次数。因此,如果你有如上所述的查询,引擎可能会认为“我必须读取表格中的所有页面,所以让我只进行全表扫描并忽略索引。”请注意,当数据位于单个页面上时,这将成立。
这也推广到其他操作。如果数据中的所有记录都适合一个数据页,那么“慢”算法通常是最好的或足够接近最佳。因此,嵌套循环连接可能比使用索引,基于散列或基于排序合并的连接更好。同样,基于排序的聚合可能比其他方法更好。
唉,我对Postgres查询优化器并不像SQL Server和Oracle那样熟悉。随着数据的增长,我确实在这些数据库中遇到了执行计划的变化。