explain计划

MySQL执行查询的方式是影响数据库性能的主要因素之一。可以使用EXPLAIN命令来验证MySQL的执
行计划。执行EXPLAIN FORMAT=JSON命令,将得到详细信息。
使用EXPALIN
explain计划提供了关于查询优化器如何执行查询的信息。只需要将EXPLAIN关键字前缀加到查询中即
可:
mysql> EXPLAIN SELECT dept_name FROM dept_emp JOIN employees ON
-> dept_emp.emp_no = employees.emp_no JOIN departments ON
-> departments.dept_no=dept_emp.dept_no
-> WHERE employees.first_name=‘Aamer’ \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: employees
partitions: NULL
type: ref
possible_keys: PRIMARY,name
key: name
key_len: 58
ref: const
rows: 228
filtered: 100.00
Extra: Using index
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: dept_emp
partitions: NULL
type: ref
possible_keys: PRIMARY,dept_no
key: PRIMARY
key_len: 4
ref: employees.employees.emp_no
rows: 1
filtered: 100.00
Extra: Using index
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: departments
partitions: NULL
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 16
ref: employees.dept_emp.dept_no
rows: 1
filtered: 100.00
Extra: NULL
云计算-legolas制作
id:
选择标识符
select_type:
表示查询的类型
table:
显示这一行的数据是关于哪张表的
partitions:
匹配的分区
type:
这是最重要的字段之一,显示查询使用了何种类型。从最好到最差的连接类型为system、const、
eq_reg、ref、range、index 和 ALL;
possible_keys:
表示查询时,可能使用的索引。指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存
在索引,则该索引将被列出,但不一定被查询使用(该查询可以利用的索引,如果没有任何索引显示
null);该列完全独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实际上不
能按生成的表次序使用。如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERE
子句看是否它引用某些列或适合索引的列来提高你的查询性能。如果是这样,创造一个适当的索引并且
再次用EXPLAIN检查查询;
key:
表示实际使用的索引。key列显示MySQL实际决定使用的键(索引),必然包含在possible_keys中。如
果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用
FORCE INDEX、USE INDEX或者IGNORE INDEX。
key_len:
索引字段的长度。表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示
的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表
内检索出的),不损失精确性的情况下,长度越短越好。
ref:
列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值;
rows:
扫描出的行数(估算的行数),表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需
要读取的行数;
filtered:
按表条件过滤的行百分比
Extra:
执行情况的描述和说明,关于MYSQL如何解析查询的额外信息
3 rows in set, 1 warning (0.00 sec)

使用EXPLAIN JSON
以JSON格式使用explain计划,能提供有关查询执行情况的完整信息:
mysql> EXPLAIN FORMAT=JSON SELECT dept_name FROM dept_emp JOIN employees ON
-> dept_emp.emp_no = employees.emp_no JOIN departments ON
-> departments.dept_no=dept_emp.dept_no
-> WHERE employees.first_name=‘Aamer’ \G
*************************** 1. row ***************************
EXPLAIN: {
“query_block”: {
“select_id”: 1,
“cost_info”: {
“query_cost”: “557.62”
},
“nested_loop”: [
{
“table”: {
“table_name”: “employees”,
“access_type”: “ref”,
“possible_keys”: [
“PRIMARY”,
“name”
],
“key”: “name”,
“used_key_parts”: [
“first_name”
],
“key_length”: “58”,
“ref”: [
“const”
],
“rows_examined_per_scan”: 228,
“rows_produced_per_join”: 228,
“filtered”: “100.00”,
“using_index”: true,
“cost_info”: {
“read_cost”: “4.49”,
“eval_cost”: “22.80”,
“prefix_cost”: “27.29”,
“data_read_per_join”: “121K”
},
“used_columns”: [
“emp_no”,
“first_name”
]
}
},
{
“table”: {
“table_name”: “dept_emp”,
“access_type”: “ref”,
“possible_keys”: [
“PRIMARY”,
“dept_no”
],
“key”: “PRIMARY”,
云计算-legolas制作
“used_key_parts”: [
“emp_no”
],
“key_length”: “4”,
“ref”: [
“employees.employees.emp_no”
],
“rows_examined_per_scan”: 1,
“rows_produced_per_join”: 251,
“filtered”: “100.00”,
“using_index”: true,
“cost_info”: {
“read_cost”: “228.12”,
“eval_cost”: “25.19”,
“prefix_cost”: “280.59”,
“data_read_per_join”: “7K”
},
“used_columns”: [
“emp_no”,
“dept_no”
]
}
},
{
“table”: {
“table_name”: “departments”,
“access_type”: “eq_ref”,
“possible_keys”: [
“PRIMARY”
],
“key”: “PRIMARY”,
“used_key_parts”: [
“dept_no”
],
“key_length”: “16”,
“ref”: [
“employees.dept_emp.dept_no”
],
“rows_examined_per_scan”: 1,
“rows_produced_per_join”: 251,
“filtered”: “100.00”,
“cost_info”: {
“read_cost”: “251.85”,
“eval_cost”: “25.19”,
“prefix_cost”: “557.62”,
“data_read_per_join”: “45K”
},
“used_columns”: [
“dept_no”,
“dept_name”
]
}
}
]
}
}
1 row in set, 1 warning (0.00 sec)
云计算-legolas制作
总结
EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
EXPLAIN不考虑各种Cache
EXPLAIN不能显示MySQL在执行查询时所作的优化工作
部分统计信息是估算的,并非精确值
EXPALIN只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划
基准查询和服务器
假设你想知道哪个查询执行起来更快。explain计划给了你一个结果,但有时并不能依据它来做决定。
如果查询时间为几十秒左右,可以在服务器上执行这些查询以判断哪个更快。但如果查询时间大约为几
毫秒,则很难基于单次执行来做判断。
可以使用mysqlslap工具模拟MySQL服务器的客户端负载,并报告每个阶段所耗费的时间,就像多个客
户端正在访问该服务器一样。
如何操作
如果想评估一条查询的执行时间。如果在MySQL客户端中执行该操作,则能够知道大致的执行时间(精
确到100ms):
可以使用mysqlslap模拟客户端负载,并在多个迭代中并行运行上述SQL语句:
以上查询是用1000个并发和100个迭代执行的,平均花费了1.614秒。
可以在文件中指定多个SQL并指定分隔符。mysqlslap会运行文件中的所有查询:
运行结果
mysql> pager grep rows
PAGER set to ‘grep rows’
mysql> SELECT e.emp_no,salary FROM salaries s JOIN employees e ON
-> s.emp_no=e.emp_no WHERE first_name=‘Adam’;
2384 rows in set (0.00 sec)
[root@www ~]# mysqlslap -uroot -pCom.123456 --create-schema=employees
> --query=“SELECT e.emp_no,salary FROM salaries s JOIN employees e ON
s.emp_no=e.emp_no WHERE first_name=‘Adam’;”
> -c 1000 -i 100
mysqlslap: [Warning] Using a password on the command line interface can be
insecure.
Benchmark
Average number of seconds to run all queries: 1.614 seconds
Minimum number of seconds to run all queries: 0.826 seconds
Maximum number of seconds to run all queries: 6.896 seconds
Number of clients running queries: 1000
Average number of queries per client: 1
[root@www script]# vim queries.sql
SELECT e.emp_no,salary FROM salaries s JOIN employees e ON s.emp_no=e.emp_no
WHERE first_name=‘Adam’;
SELECT * FROM employees WHERE first_name=‘Adam’ OR last_name=‘Adam’;
SELECT * FROM employees WHERE first_name=‘Adam’;
云计算-legolas制作
可以自动生成表和SQL语句。通过这种方式,可以将结果与之前的服务器设置进行比较:
[root@www script]# mysqlslap -uroot -pCom.123456 --create-schema=employees
> -c 10 -i 10 --query=queries.sql --delimiter=";"
mysqlslap: [Warning] Using a password on the command line interface can be
insecure.
Benchmark
Average number of seconds to run all queries: 0.922 seconds
Minimum number of seconds to run all queries: 0.843 seconds
Maximum number of seconds to run all queries: 1.039 seconds
Number of clients running queries: 10
Average number of queries per client: 3
[root@www script]# mysqlslap -uroot -pCom.123456 --create-schema=employees -c 10
-i 10
> --number-int-cols=4 --number-char-cols=10 --auto-generate-sql
mysqlslap: [Warning] Using a password on the command line interface can be
insecure.
Benchmark
Average number of seconds to run all queries: 0.049 seconds
Minimum number of seconds to run all queries: 0.042 seconds
Maximum number of seconds to run all queries: 0.059 seconds
Number of clients running queries: 10
Average number of queries per client: 0

猜你喜欢

转载自blog.csdn.net/wangboyujiayou/article/details/105955453