评论

收藏

[MySQL] distinct和order by共存对索引选择的影响

数据库 数据库 发布于:2021-07-04 10:05 | 阅读数:402 | 评论:0

  程序需要找出产品表中最新添加的状态为可用的20个产品用于客户展示
  sql语句如下
SELECT DISTINCT p.products_id, p.sj_id, p.px_id, p.products_model, p.products_p_w_picpath, pd.products_name
FROM products AS p LEFT JOIN products_description AS pd ON pd.products_id=p.products_id
WHERE 1 AND p.products_status=1 ORDER BY p.products_date_added DESC LIMIT 0, 20;
  功能上线后,发现非常慢。
  explian
+----+-------------+-------+------+---------------+---------+---------+-----------------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key   | key_len | ref             | rows  | Extra                    |
+----+-------------+-------+------+---------------+---------+---------+-----------------------------+-------+----------------------------------------------+
|  1 | SIMPLE    | p   | ALL  | NULL      | NULL  | NULL  | NULL            | 71180 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE    | pd  | ref  | PRIMARY     | PRIMARY | 4     | banggood_work.p.products_id |   1 |                        |
+----+-------------+-------+------+---------------+---------+---------+-----------------------------+-------+----------------------------------------------+
  发现products_date_added索引并没有被用上(products_date_added字段有索引,99.9%以上为products_status=1的产品),应该来讲,mysql优化器此时会选择products_date_added字段上的索引.
  仔细观察sql发现有distinct关键字,而这语句根本不需要distinct.
  此时mysql会将整个products取出来,进行去重,导致了全表扫!
  将distinct去掉,再explain
+----+-------------+-------+-------+---------------+---------------------+---------+-----------------------------+------+-------------+
| id | select_type | table | type  | possible_keys | key         | key_len | ref             | rows | Extra     |
+----+-------------+-------+-------+---------------+---------------------+---------+-----------------------------+------+-------------+
|  1 | SIMPLE    | p   | index | NULL      | products_date_added | 8     | NULL            |   20 | Using where |
|  1 | SIMPLE    | pd  | ref   | PRIMARY     | PRIMARY       | 4     | banggood_work.p.products_id |  1 |       |
+----+-------------+-------+-------+---------------+---------------------+---------+-----------------------------+------+-------------+
  发现mysql已经智能的选择了products_date_added索引,尽管该字段不再where条件上。
  

  总结
  1. mysql选择索引并不一定只会在join条件和where条件上选择,有时候也会智能的选择order by、group by上的字段
  2.distinct会干扰order by智能选择索引。distinct和order by共存对索引是有影响的,一般是在非where条件选择索引的情况下
  3. 请慎重使用distinct,不需要尽量不要用!另外可以参考我的另外一篇博文http://qdjalone.blog.51cto.com/1222376/1360112

  
关注下面的标签,发现更多相似文章