数据库
首页 > 数据库> > MySQL Explain具有与慢查询日志不同的行数

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