文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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

10.9.5 优化器成本模型

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

优化器还拥有一个成本估计数据库,用于在执行计划构建过程中使用。这些估计存储在 mysql 系统数据库中的 server_costengine_cost 表中,并且可以在任何时候配置。这些表的目的是使 DBA 可以轻松地调整优化器在尝试得出查询执行计划时使用的成本估计。

成本模型一般操作

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

  • 服务器在启动时将成本模型表读入内存,并在运行时使用内存中的值。表中指定的任何非 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;