基于代价的查询优化 - MySQL 8.0 优化指南 - 学习笔记

优化器是通过基于代价的计算方法来决定如何执行查询的(Cost-based Optimization)。简化的过程如下:

  1. 赋值每个操作的代价
  2. 计算每个可行的计划需要多少个操作
  3. 代价求和
  4. 选择总代价最低的计划

我们说上面是一个简化, 因为优化器不会不顾一切地查询所有可能的执行计划。假如一次查询有 5 个表要连接、每个表有 5 个可用索引,就会有 5!x5!=14400 种可行的查询方式:

  • 每个索引可能有不止一种访问方式。(如,索引遍历、范围遍历、按索引搜索)。另外,每个表还可以用全表扫描。
  • 对于INNER JOIN内连接查询,可以以任意顺序连表。
  • 连表时可能有多种缓存连表方式和子查询策略。

要优化器评估每一种执行计划是不可行的,试想优化花掉的时间可能比执行查询还,因此优化器会默认跳过一些计划的评估。
配置项optimizer_search_depth也可以限制对计划的搜索深度,默认不开启。


修改代价常量

每个操作的代价值都可以通过系统数据库表server_costengine_cost来配置。这里列举出一些 MySQL 8.0 中的默认值:

代价值 操作 说明
40 disk_temptable_create_cost 创建磁盘临时表代价
1 disk_temptable_row_cost 磁盘临时表每行代价
2 memory_temptable_create_cost 创建内存临时表代价
0.2 memory_temptable_row_cost 内存临时表每行代价
0.1 key_compare_cost 比较关键字代价
0.2 row_evaluate_cost 行访问代价
1 io_block_read_cost 读取磁盘块代价
1 memory_block_read_cost 读取内存块代价

提示

MySQL 8.0 加入了一项新特性:代价模型会根据内存中索引的占比去适应调整。而在早先版本的代价模型中,MySQL 认为每次访问页时磁盘IO总是必要的。

这里的“代价”是一个表示资源使用量的,逻辑上的单位。1个单位没有确切的含义,但它的起源可以追溯到1990年代,一次磁盘随机访问的代价。
随着硬件提升,各个硬件的性能对比不会一直维持相同。(例如,储存缓慢的问题被固态硬盘大幅改善了)。同样的,随着硬件中软件存址的改变(如压缩等特性),资源消耗也会改变。可配置的代价常量让我们更好地应对这些情形。

例子4 展示了改变访问行代价row_evaluate_cost为原来的 5 倍,会让全表扫描被认为的代价变得高昂很多(相比使用索引)。这会导致优化器选择使用索引。

-- 修改访问行代价为原来的5倍
UPDATE mysql.server_cost SET cost_value=1 WHERE cost_name='row_evaluate_cost';
FLUSH OPTIMIZER_COSTS;

EXPLAIN FORMAT=JSON
SELECT * FROM Country WHERE continent='Asia' and population > 5000000;
{
   "select_id": 1,
   "cost_info": {          # 因为访问行代价变为原来的5倍
   "query_cost": "325.01"  # 总查询代价提高了!
   },
   "table": {
   "table_name": "Country",
   "access_type": "range",  # 因而查询将会通过索引来执行
   "possible_keys": [
      "p"
   ],
   "key": "p",
   "used_key_parts": [
      "Population"
   ],
   "key_length": "4",
   "rows_examined_per_scan": 108,
   "rows_produced_per_join": 15,
   "filtered": "14.29",
   "index_condition": "(`world`.`Country`.`Population` > 5000000)",
   "cost_info": {
      "read_cost": "309.58",
      "eval_cost": "15.43",
      "prefix_cost": "325.01",
      "data_read_per_join": "3K"
   },
   "used_columns": [
      ...
   ],
   "attached_condition": "(`world`.`Country`.`Continent` = 'Asia')"
   }
  }
}

注意

修改代价常量一定要小心,因为许多查询计划有可能因此变得更差!上面的例子只是用于示范,大多数实际生产情形中,添加查询提示就足够做好。
在执行其他语句前记得把代价常量重置:

UPDATE mysql.server_cost SET cost_value=NULL 
WHERE cost_name='row_evaluate_cost';
FLUSH OPTIMIZER_COSTS;


元数据和统计数据

数据的分布会影响执行计划。优化器在决定的过程中,会使用数据字典和统计信息。

元数据

索引信息 唯一性 可否为null
描述 字典列出了每个表的索引。 如果一个索引具有唯一性,它可以用来做等价转换,简化执行计划的某些部分。 优化器需要正确处理可能的 null 值,可否为null 会影响部分执行计划的选用。

统计数据

表大小 基数(Cardinality) 范围估算
描述 提供了近似的表大小。 随机采样了(默认20)个页,推算出索引列中唯一值的数量。 优化器对 InnoDB 提供了最大最小值用于估算范围内的行数。
适用于 所有列 索引列 索引列
是否计算 预先计算 预先计算 需要时计算
自动更新 平时的操作中 表的 10% 被更新后 -
手动更新 使用 ANALYZE TABLE 使用 ANALYZE TABLE -
可配置项 - 页的采样数 估算索引的触发阈值、最大内存使用量
准确度 最不准确 受数据分布影响 最准确
常用于 计算全表扫描的代价;
索引较少时,分析连表顺序可能会用到。
决定连表顺序;
触发估算索引时也会用到。
条件估算(例如,查看可用的索引,估算大约能匹配多少行);
范围估算也会决定是否使用索引。

提示

因为这些数据的原因,看起来一样的查询语句在平时和生产环境中会运行得大不相同。在生产环境中,即便同一个查询计划也会随着数据分布不断变化。




译自:
Cost-based Optimization - The Unofficial MySQL 8.0 Optimizer Guide

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,548评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,069评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,985评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,305评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,324评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,030评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,639评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,552评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,081评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,194评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,327评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,004评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,688评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,188评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,307评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,667评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,337评论 2 358