MySQL 优化之执行SQL成本

EXPLAIN 升级版 EXPLAIN FORMAT=JSON SQL


一、demo 表介绍

CREATE TABLE IF NOT EXISTS {TABLE_NAME} (
  `id` varchar(32) NOT NULL,
  `time_recorded` datetime(0) NOT NULL,
  `time_updated` datetime(0) NOT NULL,
  `key1_column` int(11) NULL,
  `key2_column` int(11) NOT NULL,
  `key3_column` varchar(255) NOT NULL,
  `key4_column` varchar(255) NULL,
  `key5_column` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  INDEX `index_key1`(`key1_column`),
  UNIQUE KEY `UK_key2`(`key2_column`),
  INDEX `key_column`(`key3_column`,`key4_column`,`key5_column`)
) ENGINE = InnoDB;

test_model数据量487623
test_model数据量

test_model2数据量1001
test_model2数据量

二、例句 SQL EXPLAIN

EXPLAIN例句
从EXPLAIN 中我们可得知SQL执行大体情况,唯独不清楚执行成本(// TODO 以后更EXPLAIN各字段解释博客),这些可以通过EXPLAIN 升级版 "EXPLAIN FORMAT=JSON"得到

三、例句 SQL , EXPLAIN FORMAT=JSON

# 执行SQL
EXPLAIN FORMAT=JSON SELECT * FROM test_model INNER JOIN test_model2 ON test_model.key2_column = test_model2.key2_column WHERE test_model.time_updated < "2022-02-13 15:13:56";
# 得到json数据:
{
  "query_block": {
    "select_id": 1, # 对应EXPLAIN id列
    "cost_info": { 
      "query_cost": "1419.40" # 查询整个语句,执行成本预计时间
    },
    "nested_loop": [ # 采用嵌到循环连接算法执行查询
    # 以下是参与嵌套循环连接算法的各个表的信息
      {
        "table": {
          "table_name": "test_model2", # 驱动表, 对应EXPLAIN table字段
          "access_type": "ALL", # 访问方法为ALL, 对应EXPLAIN type字段
          "possible_keys": [ # 可能使用的索引,对应EXPLAIN possible_keys字段
            "UK_key2"
          ],
          "rows_examined_per_scan": 1001, # 查询一次test_model2表大致需要扫描数据量
          "rows_produced_per_join": 1001, # 驱动表的扇出预计数量
          "filtered": "100.00", # condition filtering代表的百分比,对应EXPLAIN filtered字段
          "cost_info": {
            "read_cost": "18.00", # IO成本 + 检查rows*(1-filter)条记录的CPU成本
            "eval_cost": "200.20", # 检查rows * filter条记录的成本
            "prefix_cost": "218.20", # 检查驱动表test_model2单独成本 read_cost + eval_cost
            "data_read_per_join": "805K" # 表示在此次查询中需要读取的数据量
          },
          "used_columns": [ # 执行查询中涉及的列
            "id",
            "time_recorded",
            "time_updated",
            "key1_column",
            "key2_column",
            "key3_column",
            "key4_column",
            "key5_column"
          ]
        }
      },
      {
        "table": {
          "table_name": "test_model", # 被驱动表, 对应EXPLAIN table字段
          "access_type": "eq_ref", # 对应EXPLAIN type字段
          "possible_keys": [ # 可能使用的索引,对应EXPLAIN possible_keys字段
            "UK_key2"
          ],
          "key": "UK_key2", # 实际使用的索引,对应EXPLAIN key字段
          "used_key_parts": [ # 使用到的索引列
            "key2_column"
          ],
          "key_length": "4", # key length,对应EXPLAIN key_len
          "ref": [ # 索引列进行等值匹配的对象,对应:test_model.key2_column = test_model2.key2_column,对应EXPLAIN ref字段
            "test_demo.test_model2.key2_column"
          ],
          "rows_examined_per_scan": 1, # 查询一次test_model大致需要扫描一条记录
          "rows_produced_per_join": 333, # 被驱动表test_model的扇出是968(由于后边没有多余的连接所以也没啥用)
          "filtered": "33.33", # condition filtering代表百分比,对应EXPLAIN filtered字段
          "cost_info": { 
            "read_cost": "1001.00", # read_cost 和 eval_cost 是访问多次累加起来的指
            "eval_cost": "66.73",
            "prefix_cost": "1419.40", # 整个连接查询预计的成本也就是单词查询test_demo2和多次查询test_demo的成本和
            "data_read_per_join": "268k" # 表示在查询中需要读取的数据量
          },
          "used_columns": [
            "id",
            "time_recorded",
            "time_updated",
            "key1_column",
            "key2_column",
            "key3_column",
            "key4_column",
            "key5_column"
          ],
          "attached_condition": "(`test_demo`.`test_model`.`time_updated` < '2022-02-13 15:13:56')" # 对test_model表访问时,针对单表查询的条件
        }
      }
    ]
  }
}

总结

可以通过"EXPLAIN FORMAT=JSON" 找出SQL执行成本

参考资料: 《MySQL是怎样运行的》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值