为了生成执行计划,优化器使用一个成本模型,该模型基于查询执行期间发生的各种操作的成本估算。优化器有一组内编译的默认值”成本的常量”它可以做出关于执行计划的决定。
优化器还有一个在执行计划构建期间使用的成本估算数据库。这些估计值存储在server_cost
而且engine_cost
中的表mysql
系统数据库和可随时配置。这些表的目的是方便地调整优化器在试图达到查询执行计划时使用的成本估计。
可配置优化器成本模型是这样工作的:
服务器在启动时将成本模型表读入内存,并在运行时使用内存中的值。任何非
零
表中指定的成本估算优先于相应的编译中的默认成本常数。任何零
Estimate指示优化器使用已编译的默认值。在运行时,服务器可能会重新读取成本表。当动态加载存储引擎时或当
冲洗OPTIMIZER_COSTS
语句执行。成本表使服务器管理员能够通过更改表中的条目轻松地调整成本估算。通过将条目的开销设置为,也很容易恢复到默认值
零
.优化器使用内存中的成本值,因此对表的更改应该跟随冲洗OPTIMIZER_COSTS
生效当客户端会话开始时,当前的内存成本估计应用于整个会话,直到会话结束。特别是,如果服务器重新读取成本表,则任何更改的估计仅适用于随后启动的会话。现有会话不受影响。
成本表特定于给定的服务器实例。服务器不会将成本表更改复制到副本。
中的优化器成本模型数据库由两个表组成mysql
包含在查询执行期间发生的操作的成本估计信息的系统数据库:
的server_cost
表包含这些列:
cost_name
成本模型中使用的成本估算的名称。名称不区分大小写。如果服务器在读取该表时不识别成本名称,则会向错误日志中写入警告。
cost_value
成本估算值。如果为“non-”
零
,服务器将其作为开销。否则,它使用默认的估计值(内编译的值)。dba可以通过更新此列来更改成本估算。如果服务器在读取该表时发现成本值无效(非正),则会向错误日志中写入警告。要覆盖默认成本估计(对于指定
零
),将开销设置为non-零
价值。若要恢复为默认值,请将该值设置为零
.然后执行冲洗OPTIMIZER_COSTS
告诉服务器重新读取成本表。last_update
最后一行更新的时间。
评论
与成本估算相关的描述性评论。dba可以使用此列提供有关成本估算行存储特定值的原因的信息。
属性的主键server_cost
表是cost_name
列,因此不可能为任何成本估计创建多个条目。
服务器会识别这些cost_name
的值。server_cost
表:
disk_temptable_create_cost
40.0(默认),disk_temptable_row_cost
1.0(默认)存储在基于磁盘的存储引擎中的内部创建的临时表的成本估计
InnoDB
或MyISAM
).增加这些值会增加使用内部临时表的成本估算,并使优化器更倾向于使用较少的查询计划。有关此类表的信息,请参见章节8.4.4,“MySQL内部临时表的使用”.与相应内存参数的默认值相比,这些磁盘参数的较大默认值(
memory_temptable_create_cost
,memory_temptable_row_cost
)反映了处理基于磁盘的表的更大成本。key_compare_cost
0.1(默认)比较记录键的开销。增加这个值会导致比较多个键的查询计划变得更昂贵。例如,执行
filesort
与使用索引避免排序的查询计划相比,成本相对较高。memory_temptable_create_cost
2.0(默认),memory_temptable_row_cost
0.2(默认)中存储的内部创建的临时表的成本估计
内存
存储引擎。增加这些值会增加使用内部临时表的成本估算,并使优化器更倾向于使用较少的查询计划。有关此类表的信息,请参见章节8.4.4,“MySQL内部临时表的使用”.这些内存参数的默认值与相应磁盘参数的默认值(
disk_temptable_create_cost
,disk_temptable_row_cost
)反映了处理基于内存的表的较低成本。row_evaluate_cost
0.2(默认)评估记录条件的成本。增加这个值会导致检查很多行的查询计划比检查更少行的查询计划成本更高。例如,与读取行数较少的范围扫描相比,表扫描的开销相对较高。
的engine_cost
表包含这些列:
engine_name
应用此成本估计的存储引擎的名称。名称不区分大小写。如果值为
默认的
,它适用于所有自己没有命名条目的存储引擎。如果服务器在读取该表时不识别引擎名称,则会向错误日志中写入警告。device_type
适用于此成本估计的设备类型。该列用于为不同的存储设备类型指定不同的成本估计,例如硬盘驱动器与固态驱动器。目前,这个信息没有被使用,并且0是唯一允许的值。
cost_name
和在
server_cost
表格cost_value
和在
server_cost
表格last_update
和在
server_cost
表格评论
和在
server_cost
表格
属性的主键engine_cost
Table是一个元组,由(cost_name
,engine_name
,device_type
)列,因此不可能为这些列中的任何值组合创建多个条目。
服务器会识别这些cost_name
的值。engine_cost
表:
io_block_read_cost
1.0(默认)从磁盘读取索引或数据块的开销。与读取较少磁盘块的查询计划相比,增加这个值会导致读取许多磁盘块的查询计划的开销增加。例如,与读取较少块的范围扫描相比,表扫描的开销相对较高。
memory_block_read_cost
1.0(默认)类似于
io_block_read_cost
,但表示从内存中的数据库缓冲区读取索引或数据块的开销。
如果io_block_read_cost
而且memory_block_read_cost
如果值不同,执行计划可能会在同一查询的两次运行之间发生变化。假设内存访问的开销小于磁盘访问的开销。在这种情况下,在服务器启动时,在将数据读入缓冲池之前,您可能会得到与运行查询之后不同的计划,因为那时数据在内存中。
对于希望将成本模型参数更改为默认值的dba,可以尝试将值加倍或减半并测量效果。
更改io_block_read_cost
而且memory_block_read_cost
参数最有可能产生有价值的结果。这些参数值使数据访问方法的成本模型能够考虑从不同来源读取信息的成本;也就是说,从磁盘读取信息与读取内存缓冲区中已经存在的信息的成本。例如,在其他条件相同的情况下io_block_read_cost
到大于的值memory_block_read_cost
导致优化器优先选择读取内存中已经保存的信息的查询计划,而不是必须从磁盘读取的计划。
此示例显示如何更改的默认值io_block_read_cost
:
更新mysql。engine_costSET cost_value = 2.0 WHERE cost_name = 'io_block_read_cost'; FLUSH OPTIMIZER_COSTS;
的值,此示例显示如何更改io_block_read_cost
只适用于InnoDB
存储引擎:
插入mysql。engine_costVALUES ('InnoDB', 0, 'io_block_read_cost', 3.0, CURRENT_TIMESTAMP, 'Using a slower disk for InnoDB'); FLUSH OPTIMIZER_COSTS;