本文翻译自Coding-Geek文章:《 How does a relational database work》。原文链接:http://coding-geek.com/how-databases-work/#Buffer-Replacement_strategies
本文翻译了如下章节, 介绍数据库的统计分析:
Statistics–数据特征统计分析
在了解数据库如何做查询优化前,我们先讲一下数据库如何做数据特征分析。没有数据特征分析的数据库不是优秀的数据库。
如果你不指令数据库分析数据,它不会主动去做,它将会做最坏的假设(没有优化空间)。数据库需要哪些类型的信息呢?
为了说清楚这个问题,我必须要简单讲一下数据库和操作系统是如何存储数据的。
它们使用一种叫页或者块的最小存储单元,默认有4KB或者8KB的大小。这意味着即使你只需要1KB的空间,它也会分配一整页的大小。如果一页是8KB,那么就有7KB被浪费了。
回到数据特征统计分析上来。当你要求数据库收集统计数据时,它将计算如下一些信息:
- 数据库表的记录行数。
- 对表的每一列,做如下处理:
- 数据去重。
- 计算数据的长度,包含最小长度、最大长度、平均长度。
- 统计数值范围。包含最小值、最大值、平均值。
- 分析表中的索引。
这些统计信息将用于帮助优化器评估查询将用到的磁盘I/O、CPU和内存大小。
对每列数据做统计分析很重要。例如:一张个人信息表将通过FIRST_NAME, LAST_NAME与其它两张表做关联查询。 统计发现这张表中的FIRST_NAME仅有1000个不同值,而LAST_NAME有1000000个不同值。数据库将修改联表顺序,将FIRST_NAME,LAST_NAME调整为LAST_NAME, FIRST_NAME。因为LAST_NAME的差异值更大,优先比较LAST_NAME能减少比较次数。大多数情况下,对于每次LAST_NAME的比较,比较两到三个字符就可以确认(两列值不同)了。
这些是最基础的统计。你也可以让数据库做更高级的统计分析(称为数据直方图)。数据直方图揭示了每一列值的分布概况。例如:
- 出现频率最高的值是什么。
- 每个值的数量。
- …
这些额外的统计信息将帮助数据库找到更优的查询方案。特别是对于等值判断(ex: WHERE AGE = 18)或者范围比较(ex: WHERE AGE > 10 and AGE <40)。
对于这类数值比较,数据库有更好的处理方案(note:专业的术语叫selectivity)。
上述统计结果存储在数据库的元数据表里面(metadata).
你可以在下面这些表中看到统计信息:
1. in USER/ALL/DBA_TABLES and USER/ALL/DBA_TAB_COLUMNS for Oracle
2. in SYSCAT.TABLES and SYSCAT.COLUMNS for DB2.
这些统计数据必须是实时的。如果一张表有1000000条记录,数据库却认为只有500条,没有什么比这更糟的了。
统计分析唯一的缺点是必须花时间去计算(这个可能很耗性能),这也是为什么大多数数据库不会自动去计算的原因。数据量大到几百万时,做数据统计分析是很困难的。在这种情况下,你可以选择只计算最基础的统计信息,或者只对部分抽样的数据做统计。
例如:我曾经参与的一个项目,每张表有几亿条数据。我只选取其中百分之十的数据做统计分析,这节省了大量时间。
糟糕的是如果选择了特定表中特定列的10%数据,这些数据与整张表的其它数据有很大的不同(译者:即选择的样本数据不具备代表性)。这些错误的统计结果将使一次只需要30s的查询花8小时。这也从另一个侧面说明了数据特征统计分析的重要性。
Note:针对不同的数据库还有一些高级的统计分析,如果想了解更多的东西,可以自行阅读数据库的官方指导文档。我上面所讲的东西来源于PostgreSQL的官方文档。