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_model2数据量1001
二、例句 SQL 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是怎样运行的》