统计信息更新与数据分布

  为了提高数据库的效率,SinoDB提供了一个基于成本的查询优化器, 当为 SinoDB数据更新统计信息时,就是将数据库表的有关统计信息更新到sysmaster库下的系统目录表中,以便查询优化器能选择最佳的执行路径。如果sysmaster库中没有相应的统计信息,或者统计信息不准确时,查询优化器就不能够选择最优的查询策略,有可能导致大量地顺序扫描,产生严重的性能问题。因此,当重新装载数据或者对数据库表进行了大量的更新操作后,应该及时执行update statistics。

一、update statistics语句

  • 更新整个数据库的统计信息

UPDATE STATISTICS [LOW|MEDIUM|HIGH];

  • 更新特定表及其索引的统计信息,或者如果没有指定tabname,更新所有表及其索引的统计信息

UPDATE STATISTICS [LOW|MEDIUM|HIGH] FOR TABLE [tabname ];

  • 更新特定列的统计信息

UPDATE STATISTICS [LOW|MEDIUM|HIGH] FOR TABLE tabname (colname);

以下是统计更新示例:

-----为整库做medium级别统计更新
update statistics medium;

-----为t_dept表做high级别统计更新
update statistics high for table t_dept;

-----为t_employee表的索引列f_employeeid做high级别统计更新
update statistics high for table t_employee(f_employeeid);

二、统计更新模式

UPDATE STATISTICS 语句提供三种统计更新模式:

  • LOW——默认模式。收集表、索引和列的统计信息,但不构建分布桶

  • MEDIUM——收集表、索引和列的统计信息,并构建描述包含 85% - 99% 精确值样本的分布桶

  • HIGH——收集表、索引和列的统计信息,并构建描述真实数据值的数据分布桶(data distribution bins)

  当使用 LOW (缺省)模式执行 UPDATE STATISTICS 语句时,数据库会收集表、索引和列的统计信息,并填入 systables,syscolumns和 sysindexes表中。

  UPDATE STATISTICS MEDIUM除了更新表、列、记录数、页数及索引等的最基本信息外,还会对列值的分布情况采取抽样的办法来进行统计,并在sysdistrib 表中填入代表该样本的分布数据。

  UPDATE STATISTICS HIGH与UPDATE STATISTICS MEDIUM的区别是在统计字段的分布情况时,后者采用了取样的办法,而前者对所有的列值排序,并将执行期间表中所有值的真实分布信息填入 sysdistrib 表。因此update statistics high更新统计最全面最精确,但是执行期间也将耗费更多资源,花费更长的时间。

三、关于数据分布

  在更新其他统计信息(例如 B+ 树的级别数量、索引使用的页的数量等)时,可使用 UPDATE STATISTICS LOW 语句中的 DROP DISTRIBUTIONS 子句删除现有的数据分布。

UPDATE STATISTICS LOW DROP DISTRIBUTIONS;
UPDATE STATISTICS LOW FOR TABLE customer DROP DISTRIBUTIONS;
UPDATE STATISTICS LOW FOR TABLE orders(order_num) DROP DISTRIBUTIONS;

  当不使用 DROP DISTRIBUTIONS 子句运行 UPDATE STATISTICS LOW 时,将只更新systables 、sysindexes 和syscolumns 里的统计信息,数据分布不会删除或改变。

  当使用 DROP DISTRIBUTIONS 子句时,所列的表或指定列上的任意分布将被删除。

  如果 ALTER TABLE 语句改变了列的数据类型或大小,数据分布也将被删除,并且必须使用 UPDATE STATISTICS 来重新创建。如果 ALTER TABLE删除了一列,分布也会被删除(分布是跟着column,不是跟着索引)。

  在某些情况下,不收集表和索引信息有利于创建新的分布数据。可以使用 UPDATE STATISTICS 语句的 DISTRIBUTIONS ONLY 子句实现这一目的。

UPDATE STATISTICS MEDIUM FOR TABLE customer DISTRIBUTIONS ONLY;

  以下命令可以查看表的数据分布情况:

dbschema -d database -hd tablename

  需要注意的是:系统将不会在 TEXT 或 BYTE 类型的列上创建数据分布。

四、解析度resolution和置信度confidence

1. 解析度resolution

  解析度resolution指定每个桶中存放数据的百分比,是 0.005 到 10 之间的任意数。

  桶的数量计算公式:100/resolution = number of bins

  解析度的值越低,创建的桶就越多。拥有越多的桶,优化器就可以越精确地考虑满足 SELECT 筛选器的行数。但是,如果分配太多的桶,优化时间也会小幅增加,因为必须要读取保存分布的系统目录页。

  HIGH 模式的缺省解析度是 0.5。MEDIUM 模式的缺省解析度是 2.5。

2. 置信度confidence

  置信度是是指分布统计时取样的比例,confidence参数的取值范围为0.80—0.99,缺省值为0.95。

  置信度只会在UPDATE STATISTICS MEDIUM 中对数据进行采样时被使用。用于 UPDATE STATISTICS MEDIUM 的样本大小取决于解析度和置信度。通过减少解析度或增加置信度值可以增加样本大小。

UPDATE STATISTICS MEDIUM for table torder RESOLUTION 1 .99

五、如何更新统计信息

  1. 对每张表,执行:

UPDATE STATISTICS MEDIUM FOR TABLE table_name DISTRIBUTIONS ONLY;

  如果表很大,可能需要指定解析度为1.0 ,置信度为 .99

  1. 对于每个索引的第一列,运行

UPDATE STATISTICS HIGH FOR TABLE table_name ( column );

  不要忘了对主键和外键约束,也要执行 UPDATE STATISTICS HIGH 语句。

  1. 如果两个多列索引以相同的列子集开始,请为第一个不同的列运行 UPDATE STATISTICS HIGH。

  例如,给定索引的定义:

CREATE INDEX ix1 ON tab1 (a,b,c,d);
CREATE INDEX ix2 ON tab1 (a,b,e,f);

  执行下列语句:

UPDATE STATISTICS HIGH FOR TABLE tab1(c);
UPDATE STATISTICS HIGH FOR TABLE tab1(e);

  1. 对于每个多列索引,对其所有列执行 UPDATE STATISTICS LOW。把多列索引里的所有列包含在一个 update statistics low 语句中,用来为每个索引更新 sysindexes,如下所示:

UPDATE STATISTICS LOW FOR TABLE tab1(a,b,c,d);
UPDATE STATISTICS LOW FOR TABLE tab1(a,b,e,f);

  1. 对小表,执行统计更新开销非常小,可以直接执行high级别的统计更新:

UPDATE STATISTICS HIGH FOR TABLE small_table;

六、何时更新统计信息

建议在以下操作之后执行统计更新操作:

  • 将数据载入到表中

  • 显著改变列中包含值的分布的更新操作

  • 删除或插入这样改变表中包含的行数的语句

  • 删除或改变表上的索引

七、利用统计信息处理问题查询

  当碰到有问题的查询SQL,感觉到比正常情况下运行慢时,使用以下步骤进行处理:

  1. 使用 SET EXPLAIN ON 运行查询以记录查询计划。

  2. 对WHERE子句中列出的列运行 UPDATE STATISTICS HIGH。

  3. 使用 SET EXPLAIN ON 运行查询,查看估计的代价是否变小?

  4. 比较前后的查询计划。如果 UDPATE STATISTICS HIGH 导致一个不同的查询计划并且估计代价更小,说明优化器做出了一个更好的选择。

  5. 除了比较之前和之后的查询计划,可能还想比较相应的运行时统计信息。为实现这一点,将 SQLSTATS 环境变量设为 2,运行查询,然后使用会话 ID 查询位于 sysmaster 数据库中的 syssqlcurses 表。

  如果UPDATE STATISTICS HIGH 改善了查询性能,可以对查询中涉及的列继续使用 UPDATE STATISTICS MEDIUM,但是这次将置信度设为 .99,并且将解析度的值稍微增加以获得更大的样本大小。然后重新运行查询,并检查查询计划,验证返回的结果是否与 HIGH 模式一样。可以重复这些操作,直到查询计划与 HIGH 模式的查询计划完全匹配。