MySQL Explain具有与慢查询日志不同的行数
作者:互联网
我在慢查询日志中有这个条目:
# User@Host: user[host] @ [ip]
# Thread_id: 1514428 Schema: db Last_errno: 0 Killed: 0
# Query_time: 2.795454 Lock_time: 0.000116 Rows_sent: 15 Rows_examined: 65207 Rows_affected: 0 Rows_read: 65207
# Bytsent: 26618
SET timestamp=1407511874;
select off.*,translated_title,translated_description
from ephpb2b_products off USE INDEX(id_viewed)
INNER JOIN ephpb2b_members mem
ON off.uid = mem.id
Left Join ephpb2b_product_language_new pol
ON off.id = pol.offer_id
and pol.language='en'
where off.approved=1
order by off.viewed
LIMIT 15;
当我解释这个查询时,它绝对没问题.
mysql> explain select off.*,translated_title,translated_description from ephpb2b_products off USE INDEX(id_viewed) INNER JOIN ephpb2b_members mem ON off.uid = mem.id Left Join ephpb2b_product_language_new pol ON off.id = pol.offer_id and pol.language='en' where off.approved=1 order by off.viewed LIMIT 15;
+----+-------------+-------+--------+-------------------------+-------------+---------+---------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------------+-------------+---------+---------------------------+------+-------------+
| 1 | SIMPLE | off | index | NULL | id_viewed | 4 | NULL | 3 | Using where |
| 1 | SIMPLE | mem | eq_ref | PRIMARY | PRIMARY | 4 | db.off.uid | 1 | Using index |
| 1 | SIMPLE | pol | ref | offer_id,id_language | offer_id | 5 | db.off.id | 4 | |
+----+-------------+-------+--------+-------------------------+-------------+---------+---------------------------+------+-------------+
3 rows in set (0.17 sec)
如何优化此查询?为什么解释显示3行和慢查询日志说它检查了65207行.
解决方法:
为了回答这个问题,您必须了解explain列上的rows列的含义,以及基于统计信息和执行后统计信息的计算之间的差异.
当您运行explain时,rows列将告诉您,对于每个表访问,将使用预期过滤器检查多少行.有两种计算方法:索引潜水(通常应该给你精确的结果)或者使用每个引擎独立存储的近似统计数据 – 每个表的5.6-.虽然可以使用第一种方法(单个索引列上的简单过滤器),但在许多情况下,只能使用近似值 – 否则,查询优化器将花费与查询执行本身一样多的时间.
在任何情况下,行都是每个表访问要读取(不返回)的计算行.即使它是精确的(并且很多次具有几个数量级的差异,但仍然对于优化器来说仍然足够好),它不会预测整个连接中访问的实际行数.例如,如果您连接表A(精确读取X行)和表B(精确读取Y行),则按顺序A – > B,读取的实际行数将是:由A(< = X)返回的X#行乘以Y,因为标准mysql仅支持嵌套循环连接. 慢速日志(如处理程序统计信息或其他分析机制)会告诉您处理和发送的实际行数,因为这些统计信息是在执行后收集的,因此是精确的. 关于你的特殊情况,EXPLAIN是值得责备的,因为它表明只有3行会被扫描进行第一次访问,而实际上它可能正在进行完整的索引扫描(因为它只使用密钥进行排序),后来得到每次执行的连接都会相乘.不要相信解释.您可以使用:
FLUSH STATUS;
-- Execute your query here
SHOW STATUS like 'Hand%';
检查行操作的实际数量和种类(PK访问,参考,索引扫描,表扫描).我会用它来单独测试每个表访问.
对于更具体的帮助,我们需要每个表的表结构和每个过滤条件的近似选择性.
标签:explain,mysql,slow-log 来源: https://codeday.me/bug/20190806/1599647.html