加入收藏 | 设为首页 | 会员中心 | 我要投稿 52站长网 (https://www.52zhanzhang.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MySQL为啥有时候会选错索引

发布时间:2022-01-18 14:15:25 所属栏目:MySql教程 来源:互联网
导读:本篇内容介绍了MySQL为什么有时候会选错索引的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 今天在生产环境中看到一个慢SQL,是个核心业务表,数据13
       本篇内容介绍了“MySQL为什么有时候会选错索引”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
 
       今天在生产环境中看到一个慢SQL,是个核心业务表,数据1300万+
 
看一下表索引:
 
mysql>show index from `order`
+-----------------+----------------------+--------------------+------------------------+-----------------------+---------------------+-----------------------+--------------------+------------------+----------------+----------------------+-------------------+-------------------------+
| Table           | Non_unique           | Key_name           | Seq_in_index           | Column_name           | Collation           | Cardinality           | Sub_part           | Packed           | Null           | Index_type           | Comment           | Index_comment           |
+-----------------+----------------------+--------------------+------------------------+-----------------------+---------------------+-----------------------+--------------------+------------------+----------------+----------------------+-------------------+-------------------------+
| order           | 0                    | PRIMARY            | 1                      | id                    | A                   | 10493505              |                    |                  |                | BTREE                |                   |                         |
| order           | 0                    | uidx_order         | 1                      | order_seq             | A                   | 10512924              |                    |                  |                | BTREE                |                   |                         |
| order           | 1                    | idx_user           | 1                      | user_id               | A                   | 1995181               |                    |                  | YES            | BTREE                |                   |                         |
| order           | 1                    | idx_shop           | 1                      | shop_id               | A                   | 53933                 |                    |                  | YES            | BTREE                |                   |                         |
| order           | 1                    | idx_out_channel    | 1                      | out_channel           | A                   | 524                   |                    |                  | YES            | BTREE                |                   |                         |
| order           | 1                    | idx_out_channel    | 2                      | out_order_no          | A                   | 10512924              |                    |                  | YES            | BTREE                |                   |                         |
| order           | 1                    | idx_order_time     | 1                      | order_time            | A                   | 9867734               |                    |                  |                | BTREE                |                   |                         |
| order           | 1                    | idx_update_time    | 1                      | update_time           | A                   | 8305698               |                    |                  |                | BTREE                |                   |                         |
| order           | 1                    | idx_create_time    | 1                      | create_time           | A                   | 9951390               |                    |                  |                | BTREE                |                   |                         |
+-----------------+----------------------+--------------------+------------------------+-----------------------+---------------------+-----------------------+--------------------+------------------+----------------+----------------------+-------------------+-------------------------+
返回行数:[9],耗时:4 ms.
mysql>SELECT id,order_seq,user_id
FROM
`ORDER`
WHERE
delete_flag = 0
AND user_id = 'd4b0c318b28a46968718dddbaf4775c0'
AND display_status = 2
ORDER BY
order_time asc
LIMIT 0,20
+--------------+---------------------+----------------------------------+
| id           | order_seq           | user_id                          |
+--------------+---------------------+----------------------------------+
| 6068129      | 20161128183300861   | d4b0c318b28a46968718dddbaf4775c0 |
| 6118611      | 20161206171509550   | d4b0c318b28a46968718dddbaf4775c0 |
| 6885081      | 20170427104933189   | d4b0c318b28a46968718dddbaf4775c0 |
| 7720299      | 2017101718252243    | d4b0c318b28a46968718dddbaf4775c0 |
| 10319613     | 201905281103186182  | d4b0c318b28a46968718dddbaf4775c0 |
| 505498       | 2019082116584284235 | d4b0c318b28a46968718dddbaf4775c0 |
| 10840144     | 1119082315041792571 | d4b0c318b28a46968718dddbaf4775c0 |
+--------------+---------------------+----------------------------------+
返回行数:[7],耗时:18534 ms.
耗时18s,这个查询速度肯定是不能接受的。
 
我们看一下执行计划:
 
mysql>EXPLAIN SELECT id,order_seq,user_id
FROM
`ORDER`
WHERE
delete_flag = 0
AND user_id = 'd4b0c318b28a46968718dddbaf4775c0'
AND display_status = 2
ORDER BY
order_time asc
LIMIT 0,20
+--------------+-----------------------+-----------------+----------------------+----------------+-------------------------+----------------+-------------------+---------------+----------------+--------------------+-----------------+
| id           | select_type           | table           | partitions           | type           | possible_keys           | key            | key_len           | ref           | rows           | filtered           | Extra           |
+--------------+-----------------------+-----------------+----------------------+----------------+-------------------------+----------------+-------------------+---------------+----------------+--------------------+-----------------+
| 1            | SIMPLE                | ORDER           |                      | index          | idx_user                | idx_order_time | 5                 |               | 2705           |               0.01 | Using where     |
+--------------+-----------------------+-----------------+----------------------+----------------+-------------------------+----------------+-------------------+---------------+----------------+--------------------+-----------------+
 执行计划中看到,这个SQL走索引idx_order_time,根据经验判断,此索引效率很差。而扫描行数为2705,慢日志显示扫描行数为13,347,074,二者相差甚远,那么为什么会出现如此大的差异呢?
 
        选择索引是优化器的工作。而优化器选择索引的目的,是找一个最优的执行方案,并用最小的代价去执行语句。在数据库里面,扫描行数是影响执行代价的因素之一。扫描的行数越少,意味着访问磁盘数据的次数越少,消耗的CPU资源越少。
 
        当然,扫描行数并不是唯一的判断标准,优化器还会结合是否使用临时表,是否排序等因素进行综合判断。扫描行数是怎么判断的?
 
        MySQL在真正执行SQL之前,并不能准确的判断满足这个条件的数据有多少行,只能按统计信息来估算行数。
 
索引的统计信息就是索引的“区分度”,一个索引不同的值越多,这个索引的区分度就越好,而一个索引上不同的值的个数,我们称之为“基数”,基数越大,索引的区分度越好。

(编辑:52站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读