文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  优化器成本模型

10.9.5 优化器成本模型

为了生成执行计划,优化器使用成本模型,该模型基于对查询执行过程中发生的各种操作成本的估计。优化器有一组编译好的默认成本常量,可以用来做出有关执行计划的决策。

优化器还拥有一个成本估计数据库,在构建执行计划期间使用这些估计。这些估计存储在mysql系统数据库中的server_costengine_cost表中,并且可以随时配置。这些表的意图是使优化器在尝试得出查询执行计划时,能够轻松地调整其使用的成本估计。

成本模型一般操作

可配置的优化器成本模型的工作原理如下

  • 服务器在启动时将成本模型表读取到内存中,并在运行时使用内存中的值。表中指定的任何非NULL成本估计优先于相应的编译好的默认成本常量。任何NULL估计表示优化器使用编译好的默认值。

  • 在运行时,服务器可能会重新读取成本表。当动态加载存储引擎或执行FLUSH OPTIMIZER_COSTS语句时,就会发生这种情况。

  • 成本表使服务器管理员可以通过更改表中的条目轻松地调整成本估计。通过将条目的成本设置为NULL,也可以轻松地恢复到默认值。优化器使用内存中的成本值,因此对表的更改应在执行FLUSH OPTIMIZER_COSTS之后生效。

  • 在客户端会话开始时当前的内存中成本估计会应用于该会话的整个过程,直到该会话结束。特别是,如果服务器重新读取成本表,任何更改的估计仅适用于随后启动的会话。现有会话不受影响。

  • 成本表特定于给定的服务器实例。服务器不会将成本表更改复制到副本。

成本模型数据库

优化器成本模型数据库由mysql系统数据库中的两个表组成,这些表包含在查询执行期间发生的运算的成本估计信息

  • server_cost:优化器对一般服务器运算的成本估计

  • engine_cost:优化器对特定存储引擎的运算的成本估计

server_cost表包含以下列

  • cost_name

    成本模型中使用的成本估计的名称。名称不区分大小写。如果服务器在读取此表时无法识别成本名称,它会将警告写入错误日志。

  • cost_value

    成本估计值。如果该值是非NULL,则服务器将其用作成本。否则,它使用默认估计(编译好的值)。DBA 可以通过更新此列来更改成本估计。如果服务器发现成本值在读取此表时无效(非正数),它会将警告写入错误日志。

    要覆盖默认成本估计(对于指定NULL的条目),请将成本设置为非NULL值。要恢复到默认值,请将值设置为NULL。然后执行FLUSH OPTIMIZER_COSTS来告诉服务器重新读取成本表。

  • last_update

    最后一次行更新的时间。

  • comment

    与成本估计相关联的描述性注释。DBA 可以使用此列提供有关成本估计行存储特定值的原因的信息。

  • default_value

    成本估计的默认(编译好的)值。此列是一个只读生成的列,即使关联的成本估计发生更改,其值也会保留。对于在运行时添加到表的行,此列的值为NULL

server_cost 的主键是 cost_name 列,因此无法为任何成本估计创建多个条目。

服务器识别表 server_cost 中的以下 cost_name 值:

  • disk_temptable_create_costdisk_temptable_row_cost

    在基于磁盘的存储引擎(InnoDBMyISAM)中存储的内部创建临时表的成本估计。增加这些值会增加使用内部临时表的成本估计,并使优化器更倾向于使用更少使用内部临时表的查询计划。有关此类表的更多信息,请参阅 第 10.4.4 节,“MySQL 中的内部临时表使用”

    与相应的内存参数(memory_temptable_create_costmemory_temptable_row_cost)相比,这些磁盘参数的默认值更大,反映了处理基于磁盘的表所带来的更高成本。

  • key_compare_cost

    比较记录键的成本。增加此值会导致比较许多键的查询计划变得更昂贵。例如,执行 filesort 的查询计划会变得相对更昂贵,而使用索引避免排序的查询计划则会变得相对更便宜。

  • memory_temptable_create_costmemory_temptable_row_cost

    MEMORY 存储引擎中存储的内部创建临时表的成本估计。增加这些值会增加使用内部临时表的成本估计,并使优化器更倾向于使用更少使用内部临时表的查询计划。有关此类表的更多信息,请参阅 第 10.4.4 节,“MySQL 中的内部临时表使用”

    与相应的磁盘参数(disk_temptable_create_costdisk_temptable_row_cost)相比,这些内存参数的默认值更小,反映了处理基于内存的表所带来的更低成本。

  • row_evaluate_cost

    评估记录条件的成本。增加此值会导致检查许多行的查询计划变得更昂贵,而检查更少行的查询计划则会变得相对更便宜。例如,表扫描会变得相对更昂贵,而读取更少行的范围扫描则会变得相对更便宜。

engine_cost 包含以下列:

  • engine_name

    此成本估计所应用的存储引擎的名称。名称不区分大小写。如果值为 default,则它适用于所有没有自己的命名条目的存储引擎。如果服务器在读取此表时无法识别引擎名称,它会向错误日志写入警告。

  • device_type

    此成本估计所应用的设备类型。此列旨在为不同的存储设备类型指定不同的成本估计,例如硬盘驱动器与固态驱动器。目前,此信息未使用,并且 0 是唯一允许的值。

  • cost_name

    与表 server_cost 中的相同。

  • cost_value

    与表 server_cost 中的相同。

  • last_update

    与表 server_cost 中的相同。

  • comment

    与表 server_cost 中的相同。

  • default_value

    成本估计的默认(编译时)值。此列是一个只读的生成列,即使关联的成本估计发生更改,它也会保留其值。对于在运行时添加到表的行,此列的值为 NULL,但如果该行具有与原始行之一相同的 cost_name 值,则 default_value 列具有与该行相同的值。

engine_cost 的主键是一个元组,包含 (cost_nameengine_namedevice_type) 列,因此无法为这些列中的任何值组合创建多个条目。

服务器识别表 engine_cost 中的以下 cost_name 值:

  • io_block_read_cost

    从磁盘读取索引或数据块的成本。增加此值会导致读取许多磁盘块的查询计划变得更昂贵,而读取更少磁盘块的查询计划则会变得相对更便宜。例如,表扫描会变得相对更昂贵,而读取更少块的范围扫描则会变得相对更便宜。

  • memory_block_read_cost

    类似于 io_block_read_cost,但代表从内存中数据库缓冲区读取索引或数据块的成本。

如果 io_block_read_costmemory_block_read_cost 值不同,则相同查询的两次运行之间的执行计划可能会发生变化。假设内存访问的成本低于磁盘访问的成本。在这种情况下,在服务器启动之前数据已读入缓冲池,您可能会得到与查询运行后不同的计划,因为此时数据已在内存中。

更改成本模型数据库

对于希望更改成本模型参数的默认值的 DBA,请尝试将值加倍或减半,并衡量其效果。

io_block_read_costmemory_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;