MySQL是一个经典的C/S架构。服务器分两层:第一层是Server层,第二层是存储引擎。Server层处理主要的业务操作流程,不关心具体的存储逻辑。存储逻辑由存储引擎层去实现,常见的存储引擎有InnoDB(默认的)、MyISAM、Memory等。
MySQL的优化器主要是将SQL经过语法解析/词法解析后得到的语法树,通过MySQL的数据字典和统计信息的内容,经过一系列运算,从而得出一个执行计划树的构成。之后MySQL按照执行树的要求,计算得出结果。也就是说优化器的输入是一个语法树,输出是一个执行树(也称为执行计划)。通过explain查看执行计划。
统计信息 描述了 表格或者索引视图中的某些列的值 的分布情况,属于数据库对象。 根据统计信息,查询优化器就能评估查询过程中需要读取的行数及结果集情况,同时也能创建高质量的查询计划。 有了统计信息,查询优化器可以使用基数估计来选择合理的索引,而不需要耗费更多的IO资源扫描来评估哪个索引合理,能有效提供查询性能。
优化器选择索引的目的,是找到一个最优的执行方案,并用最小的代价去执行语句。在数据库里面,扫描行数是影响执行代价的因素之一。扫描的行数越少,意味着访问磁盘数据的次数越少,消耗的 CPU 资源越少。当然,扫描行数并不是唯一的判断标准,优化器还会结合是否使用临时表、是否排序等因素进行综合判断。
MySQL 在真正开始执行语句之前,并不能精确地知道满足这个条件的记录有多少条,而只能根据统计信息来估算记录数,这个统计信息就是索引的“区分度”。显然,一个索引上不同的值越多,这个索引的区分度就越好。而一个索引上不同的值的个数,我们称之为“基数”(cardinality)。也就是说,这个基数越大,索引的区分度越好。
优化器主要分为两个阶段,首先是逻辑查询优化,这个阶段主要是使用关系代数对SQL语句做一些等价变换,对条件表达式进行等价谓词重写、条件简化,对视图进行重写,对子查询进行优化,对连接语义进行了外连接消除、嵌套连接消除等。其次是物理查询优化。物理查询优化一般分为两种:
基于规则的优化(RBO,Rule-Based Optimizer)
这种方式主要是基于一些预置的规则对查询进行优化。
基于代价的优化(CBO,Cost-Based Optimizer)
这种方式会根据模型计算出各个可能的执行计划的代价,然后选择代价最少的那个。它会利用数据库里面的统计信息来做判断。
MySQL 查询优化器的主要功能是完成SELECT语句的执行,在保证SELECT语句正确执行之外,使用关系代数、启发式规则、代价估值模型等不同种类的技术,提高SELECT语句的执行效率。