MySQL5.7官方文档翻译--优化器成本模型

成本模型,也有叫做代价模型,原文是Cost Model,下面翻译都使用成本模型

 

8.9.5 优化器的成本模型

SQL查询的方式多种多样,MySQL的优化器使用基于对查询成本进行预估的成本模型来生成执行方案。优化器拥有一系列编译过的“成本常量”来决定使用怎样的执行方案。

除了编译过的成本常量之外,优化器在构建执行方案的时候还会用到一个数据库,也是用来做成本评估的。这些成本评估用的数据保存在mysql的系统库(库名是mysql),server_cost表和engine_cost表中,这两个表中的数据项是随时可以修改的。这些表存在的意义就是让优化器在准备执行方案的时候可以比较简单的判断查询成本。

1,成本模型的基本操作

2,成本模型的数据库

3,成本模型数据库的修改方式

 

成本模型的基本工作方式

这些可配置的成本模型是这样工作的:

1,SQL服务在启动的时候从成本模型的数据库表中读取数据,存到内存,运行期间就从内存中读取这些数据。这个表中非NULL的值的优先级高于编译好的默认值,这个表中的NULL值代表优化器使用编译好的默认值。

2,SQL服务运行的时候可能会重新读取成本表。重新读取的场景有:存储引擎的动态加载,和执行FLUSH OPTIMIZER_COSTS语句。

3,内存中的成本评估数据对于客户端的会话(session)来说是实时的,贯串了会话的开始到结束。注意,如果SQL服务重新读取了成本表,表中修改的信息只对后面生成的会话生效,对即将结束的会话不会起作用。

4,成本评估表是对指定的SQL服务实例生效的,SQL服务不会把成本评估表的修改同步到从库去。 

 

成本模型表

优化器的成本模型表包含两张表,在mysql的系统库(库名是mysql)中,表中保存了查询的时候需要用到的成本评估的信息。

1,server_cost。服务通用的成本评估信息表。

2,engine_cost。特定存储引擎的成本评估信息表。

 

server_cost表包含以下字段:

1,cost_name

成本评估的时候用的名字。这个名字是非大小写敏感的。如果当SQL服务读取这个表的时候发现了自己不认识的名字,会在错误日志中记录一条警告日志。

2,cost_value

成本评估项的具体值。如果这个值是非NULL的,SQL服务就会使用这个值,否则SQL服务会使用默认值(编译好的值)。数据库管理员可以通过修改这个值来影响成本评估的结果。如果当SQL服务读取这个表时发现值是非法的(比如负数),会在错误日志中记录一条警告日志。

如果想要覆盖系统默认值(往往成本评估表里没有这一条记录),把这个值改成非NULL就可以了。如果想要恢复使用系统默认值,就把这个值改回NULL就可以。然后要执行FLUSH OPTIMIZER_COSTS语句,然后SQL服务会重新读取这些成本模型表。

3,last_update

该行数据的上次更新时间。

4,comment

该项评估信息的备注。数据库管理员可以在这一栏写备注,比如为什么要设置这么个值等等。

 server_cost表的主键是cost_name字段,所以cost_name肯定不会重复。

 

server_cost表的cost_name字段可以有这些值:

1,disk_temptable_create_cost(默认 40.0), disk_temptable_row_cost (默认 1.0)

在基于磁盘的存储引擎中建立临时表时的成本评估值(比如InnoDB和MyISAM)。如果这些值增大,优化器会认为建立临时表的成本增大,从而减少使用临时表。关于临时表的更多信息参见章节8.4.4, “Internal Temporary Table Use in MySQL”。

如果这些磁盘相关参数大于内存相关参数(比如memory_temptable_create_cost, memory_temptable_row_cost)的话,代表处理磁盘上的临时表有着更多的成本。

2,key_compare_cost (默认 0.1)

比较记录中关键字时的成本。如果这个值增大,代表在查询计划中,比较多种关键字这种操作的成本增大了。比如,和使用索引而避免排序的查询计划相比,文件索引(filesort)的成本变的相对更高了。

3,memory_temptable_create_cost(默认 2.0), memory_temptable_row_cost (默认 0.2)

在基于内存的存储引擎(比如MEMORY)中建立临时表时的成本评估值。如果这些值增大,优化器会认为建立临时表的成本增大,从而减少使用临时表。关于临时表的更多信息参见章节8.4.4, “Internal Temporary Table Use in MySQL”。

如果这些内存相关参数小于磁盘相关参数(比如disk_temptable_create_cost, disk_temptable_row_cost)的话,代表处理内存上的表有着更少的成本。

4,row_evaluate_cost (默认0.2)

评估查询条件的成本。如果这个值增大,代表查询更多行的执行计划的成本变得更大了。比如,和范围查询相比,全表扫描的成本相对变得更大了。

 

engine_cost表包含以下字段:

1,engine_name

成本评估的时候用的名字。这个名字是非大小写敏感的。如果这个值是default,那些没有配置自己名字的存储引擎都会使用这个参数。如果当SQL服务读取这个表的时候发现了自己不认识的名字,会在错误日志中记录一条警告日志。

2,device_type

成本评估生效的设备类型。这一栏是为了区别不同的磁盘设备而设计的,比如区分传统的硬盘和固态硬盘。目前这一栏还没有用到,值也只能设为0。

3,cost_name

和server_cost表中功能一样。

4,cost_value

和server_cost表中功能一样。

4,last_update

和server_cost表中功能一样。

5,comment

和server_cost表中功能一样。

engine_cost表的主键是一个联合索引,包含了cost_name,engine_name,device_type列,所以这些列组成的联合键值是不会重复的。

 

engine_cost表中的cost_name可以有以下值:

1,io_block_read_cost (默认1.0)

从磁盘上读取一个索引块或数据块的成本。如果这个值增大,代表读取多个硬盘块的查询计划变得成本更高了。比如,和范围查询相比,全表扫描的成本相对变得更大了。

2, memory_block_read_cost (默认1.0)

和io_block_read_cost差不多,只不过这个值代表从内存数据库中读取数据块时的成本。

如果io_block_read_cost和memory_block_read_cost的值不一样,那么即使是同一个查询,执行两次sql时的执行计划也会不一样。假设访问内存的成本比访问磁盘的成本低,那么,数据加载到缓冲池之前执行sql和第二次执行该sql相比得到的执行计划就可能不同,因为第二次执行的时候数据已经在缓冲池里了。

 

修改成本评估模型的数据库

如果数据库管理员要修改成本模型的值,建议加倍或者减半这些值,然后看看效果。

对io_block_read_cost和memory_block_read_cost的修改可能效果是最好的。这两个参数可以让成本模型的数据读取模块决定从磁盘读数据还是从内存读数据。比如,在其他设置都一样的情况下,如果把io_block_read_cost设置的比memory_block_read_cost大,那么优化器会更愿意选择从内存中读取数据的执行计划,而不是从磁盘中读取数据的执行计划。

下面举个例子,怎样修改io_block_read_cost的默认值:

 

UPDATE mysql.engine_cost

 SET cost_value = 2.0

 WHERE cost_name = 'io_block_read_cost';

FLUSH OPTIMIZER_COSTS;

下面举个例子,怎样修改InnoDB引擎的io_block_read_cost的默认值:

 

INSERT INTO mysql.engine_cost

 VALUES ('InnoDB', 0, 'io_block_read_cost', 3.0,

 CURRENT_TIMESTAMP, 'Using a slower disk for InnoDB');

FLUSH OPTIMIZER_COSTS;

 

以上就是MySQL官网对于优化器成本模型一章的翻译,MySQL版本5.7,章节是8.9.5。

 

不知道5.7的文档有没有人翻译过,鉴于英语水平有限,要是有翻译不准确的地方欢迎指正。

官方文档中这个章节的地址:https://dev.mysql.com/doc/refman/5.7/en/cost-model.html#cost-model-operation

 

你可能感兴趣的:(MySQL)