SQL优化案例1--去掉双%%后,SQL速度从5秒到0.01秒

一、问题现象

  开发说以下SQL执行15秒,不可以接受。你把他优化到0.1秒以下吧。(跟客户交流过,SQL需要经过处理)

SELECT *
  FROM orde
  left join user
    on orde.user_id = user.id
  left join car
    on orde.car_id = car.id
  left join ocm
    on orde.charge_stand_encod = ocm.charge_stand_encod
  left join admin
    on orde.update_userid = admin.id
  LEFT JOIN scl
    on scl.id = orde.coupon_id
  LEFT JOIN sct
    on scl.coupon_type_id = sct.id
 WHERE 1 = 1
   AND user.phone like '%17885004325%'
   AND orde.operator_id in (10,
                            7,
                            1048,
                            8,
                            9,
                            998,
                            1001,
                            1002,
                            1005,
                            1006,
                            1007,
                            1009,
                            1010,
                            1011,
                            1024,
                            1012,
                            1020,
                            1013,
                            1014,
                            1015)
 ORDER BY orde.create_time DESC limit 0, 20

 

二、信息收集

查看表数据量

 

+------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+--------------+
| Name       | Engine | Version | Row_format | Rows    | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options | Comment      |
+------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+--------------+
| orde       | InnoDB |      10 | Dynamic    | 1551182 |            984 |  1527758848 |               0 |    787513344 |   7340032 |       10336667 | 2018-09-05 20:31:17 | 2018-10-30 17:21:57 | NULL       | utf8_general_ci |     NULL |                | 订单总表     |
+------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+--------------+


+------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+-----------+
| Name       | Engine | Version | Row_format | Rows    | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options | Comment   |y
+------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+-----------+
| user       | InnoDB |      10 | Dynamic    | 1537890 |            371 |   571457536 |               0 |    335577088 |   4194304 |       12112311 | 2018-10-19 23:01:12 | 2018-10-30 17:21:57 | NULL       | utf8_general_ci |     NULL |                | 会员表    |
+------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+-----------+


+--------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+--------------+
| Name         | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options | Comment      |
+--------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+--------------+
| car          | InnoDB |      10 | Dynamic    | 7057 |            807 |     5701632 |               0 |      5226496 |   4194304 |          42404 | 2018-10-01 00:14:35 | 2018-10-30 17:21:57 | NULL       | utf8_general_ci |     NULL |                | 车辆信息     |
+--------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+----------------+--------------+


+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+
| Name            | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options     | Comment |
+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+
| ocm | InnoDB    |      10 | Compact    |  153 |            321 |       49152 |               0 |        16384 |         0 |            811 | 2018-06-13 01:03:40 | 2018-10-30 15:00:42 | NULL       | utf8_general_ci |     NULL | row_format=COMPACT |         |
+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+


+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------+----------+--------------------+---------+
| Name            | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation | Checksum | Create_options     | Comment |
+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------+----------+--------------------+---------+
| admin | InnoDB  |      10 | Compact    |  631 |            207 |      131072 |               0 |        32768 |         0 |           1686 | 2018-06-13 01:03:41 | 2018-10-30 16:27:31 | NULL       | utf8_bin  |     NULL | row_format=COMPACT |         |
+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------+----------+--------------------+---------+


+-----------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+
| Name            | Engine | Version | Row_format | Rows    | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options     | Comment |
+-----------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+
| scl             | InnoDB |      10 | Compact    | 6498194 |            163 |  1061142528 |               0 |    533102592 |   7340032 |       44548696 | 2018-10-18 23:02:45 | 2018-10-30 17:21:57 | NULL       | utf8_general_ci |     NULL | row_format=COMPACT |         |
+-----------------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+


+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+
| Name            | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time | Collation       | Checksum | Create_options     | Comment |
+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+
| sct             | InnoDB |      10 | Compact    | 6456 |            246 |     1589248 |               0 |        98304 |   4194304 |          12356 | 2018-07-19 19:34:17 | 2018-10-30 16:58:35 | NULL       | utf8_general_ci |     NULL | row_format=COMPACT |         |
+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+---------------------+------------+-----------------+----------+--------------------+---------+

 

查看表上面的索引

+------------+------------+-------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table      | Non_unique | Key_name                | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+------------+------------+-------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| orde       |          0 | PRIMARY                 |            1 | id            | A         |     1634857 |     NULL | NULL   |      | BTREE      |         |               |
| orde       |          1 | update_userid           |            1 | update_userid | A         |      167598 |     NULL | NULL   | YES  | BTREE      |         |               |
| orde       |          1 | oper_orders_update_time |            1 | update_time   | A         |     1410960 |     NULL | NULL   | YES  | BTREE      |         |               |
| orde       |          1 | ope_orders_uid          |            1 | user_id       | A         |      159562 |     NULL | NULL   |      | BTREE      |         |               |
| orde       |          1 | order_id_index          |            1 | order_id      | A         |     1634865 |     NULL | NULL   | YES  | BTREE      |         |               |
| orde       |          1 | begin_time_index        |            1 | begin_time    | A         |     1277148 |     NULL | NULL   | YES  | BTREE      |         |               |
| orde       |          1 | end_time                |            1 | end_time      | A         |     1531872 |     NULL | NULL   | YES  | BTREE      |         |               |
| orde       |          1 | create_time_index       |            1 | create_time   | A         |     1628670 |     NULL | NULL   | YES  | BTREE      |         |               |
| orde       |          1 | car_id_index            |            1 | car_id        | A         |        8313 |     NULL | NULL   | YES  | BTREE      |         |               |
| orde       |          1 | idx_operator_id         |            1 | operator_id   | A         |          18 |     NULL | NULL   | YES  | BTREE      |         |               |
| orde       |          1 | idx_status              |            1 | status        | A         |           8 |     NULL | NULL   | YES  | BTREE      |         |               |
| orde       |          1 | idx_user_id             |            1 | user_id       | A         |      162152 |     NULL | NULL   |      | BTREE      |         |               |
+------------+------------+-------------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

+------------+------------+-----------------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table      | Non_unique | Key_name                    | Seq_in_index | Column_name     | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+------------+------------+-----------------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user       |          0 | PRIMARY                     |            1 | id              | A         |     1320970 |     NULL | NULL   |      | BTREE      |         |               |
| user       |          0 | web_user_phone_unique_index |            1 | phone           | A         |     1320979 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          0 | web_user_phone_unique_index |            2 | top_operator_id | A         |     1320979 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          1 | user_name                   |            1 | user_name       | A         |         205 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          1 | user_type                   |            1 | user_type       | A         |           2 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          1 | province                    |            1 | province        | A         |          29 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          1 | is_have_order               |            1 | is_have_order   | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          1 | rfid                        |            1 | rfid            | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          1 | idx_operator_id             |            1 | operator_id     | A         |          19 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          1 | idx_create_time             |            1 | create_time     | A         |     1232045 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          1 | invitation_code             |            1 | invitation_code | A         |      566384 |     NULL | NULL   | YES  | BTREE      |         |               |
| user       |          1 | i_imei                      |            1 | imei            | A         |      469607 |     NULL | NULL   | YES  | BTREE      |         |               |
+------------+------------+-----------------------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

+--------------+------------+--------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table        | Non_unique | Key_name                 | Seq_in_index | Column_name          | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------+------------+--------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| car          |          0 | PRIMARY                  |            1 | id                   | A         |        7121 |     NULL | NULL   |      | BTREE      |         |               |
| car          |          0 | idx_plate                |            1 | plate                | A         |        7121 |     NULL | NULL   |      | BTREE      |         |               |
| car          |          1 | city_code                |            1 | city_code            | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |               |
| car          |          1 | user_id                  |            1 | user_id              | A         |        2390 |     NULL | NULL   | YES  | BTREE      |         |               |
| car          |          1 | order_id                 |            1 | order_id             | A         |        2402 |     NULL | NULL   | YES  | BTREE      |         |               |
| car          |          1 | car_is_in_rail           |            1 | car_is_in_rail       | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |               |
| car          |          1 | amap_id                  |            1 | amap_id              | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |               |
| car          |          1 | ope_car_info             |            1 | device_num           | A         |        7121 |     NULL | NULL   | YES  | BTREE      |         |               |
| car          |          1 | idx_deposit_rail_draw_id |            1 | deposit_rail_draw_id | A         |        1165 |     NULL | NULL   | YES  | BTREE      |         |               |
| car          |          1 | idx_deposit_rail_draw_id |            2 | car_now_status       | A         |        1553 |     NULL | NULL   | YES  | BTREE      |         |               |
+--------------+------------+--------------------------+--------------+----------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

+-----------------+------------+-----------------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table           | Non_unique | Key_name                    | Seq_in_index | Column_name        | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+-----------------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| ocm             |          0 | PRIMARY                     |            1 | id                 | A         |         101 |     NULL | NULL   |      | BTREE      |         |               |
| ocm             |          1 | ope_charge_main_charge_code |            1 | charge_stand_encod | A         |         101 |     NULL | NULL   |      | BTREE      |         |               |
+-----------------+------------+-----------------------------+--------------+--------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

+-----------------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table           | Non_unique | Key_name         | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| admin           |          0 | PRIMARY          |            1 | id          | A         |         732 |     NULL | NULL   |      | BTREE      |         |               |
| admin           |          0 | user_name_unique |            1 | user_name   | A         |         732 |     NULL | NULL   | YES  | BTREE      |         |               |
| admin           |          1 | user_code        |            1 | user_code   | A         |         670 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

+-----------------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table           | Non_unique | Key_name                | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| scl             |          0 | PRIMARY                 |            1 | id          | A         |     5043168 |     NULL | NULL   |      | BTREE      |         |               |
| scl             |          1 | is_delete               |            1 | is_delete   | A         |           1 |     NULL | NULL   | YES  | BTREE      |         |               |
| scl             |          1 | scl_user_id |            1 | user_id     | A         |      611029 |     NULL | NULL   | YES  | BTREE      |         |               |
| scl             |          1 | idx_create_time         |            1 | create_time | A         |      856759 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------------+------------+-------------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

+-----------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table           | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-----------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| sct             |          0 | PRIMARY   |            1 | id          | A         |        5590 |     NULL | NULL   |      | BTREE      |         |               |
| sct             |          1 | is_delete |            1 | is_delete   | A         |           2 |     NULL | NULL   | YES  | BTREE      |         |               |
+-----------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

 

查看SQL执行计划

+----+-------------+-------+------------+--------+--------------------------------------------+-----------------------------+---------+--------------------------------------+------+----------+-------------+
| id | select_type | table | partitions | type   | possible_keys                              | key                         | key_len | ref                                  | rows | filtered | Extra       |
+----+-------------+-------+------------+--------+--------------------------------------------+-----------------------------+---------+--------------------------------------+------+----------+-------------+
|  1 | SIMPLE      | orde  | NULL       | index  | ope_orders_uid,idx_operator_id,idx_user_id | create_time_index           | 6       | NULL                                 |   19 |   100.00 | Using where |
|  1 | SIMPLE      | user  | NULL       | eq_ref | PRIMARY                                    | PRIMARY                     | 4       | bq_bjev_gxqc.orde.user_id            |    1 |   100.00 | Using where |
|  1 | SIMPLE      | car   | NULL       | eq_ref | PRIMARY                                    | PRIMARY                     | 4       | bq_bjev_gxqc.orde.car_id             |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | ocm   | NULL       | ref    | ope_charge_main_charge_code                | ope_charge_main_charge_code | 8       | bq_bjev_gxqc.orde.charge_stand_encod |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | admin | NULL       | eq_ref | PRIMARY                                    | PRIMARY                     | 4       | bq_bjev_gxqc.orde.update_userid      |    1 |   100.00 | Using index |
|  1 | SIMPLE      | scl   | NULL       | eq_ref | PRIMARY                                    | PRIMARY                     | 8       | bq_bjev_gxqc.orde.coupon_id          |    1 |   100.00 | Using where |
|  1 | SIMPLE      | sct   | NULL       | eq_ref | PRIMARY                                    | PRIMARY                     | 4       | bq_bjev_gxqc.scl.coupon_type_id      |    1 |   100.00 | NULL        |
+----+-------------+-------+------------+--------+--------------------------------------------+-----------------------------+---------+--------------------------------------+------+----------+-------------+

 

三、分析思路

id都是1,表连接顺序从上往下

orde 表数据量 1551182,用到索引 create_time_index,type 是 index,表示是全索引扫描。extra是using where ,表示使用了 where 过滤。实际统计结果如下

select count(*) from orde
where orde.operator_id in (10,7,1048,8,9,998,1001,1002,1005,1006,1007,1009,1010,1011,1024,1012,1020,1013,1014,1015)
+----------+
| count(*) |
+----------+
|  1717046 |
+----------+

结果是 170万行,比原来的150万还要大,很明显统计信息不准确。MySQL实际肯定会拿着170万的数据去跟下一个表做关联的,这将会很恐怖。

 

接下来是user表,用到索引 primary,type 是 eq_ref,表示是唯一索引扫描。多表连接中使用主键或者唯一索引作为关联条件。extra也是using where,实际统计结果如下

select count(*) from user
where user.phone like '%17885004325%';
+----------+
| count(*) |
+----------+
|        1 |
+----------+

结果只有一条。而且 user 表,phone字段上面是有索引的,基数也很高。为什么没有用到索引,细心的朋友应该发现了。用了两个%%,这是走不了索引的。

把两个%%去掉之后,执行速度在0.01秒。接下来看一下执行计划

+----+-------------+-------+------------+--------+--------------------------------------------+-----------------------------+---------+--------------------------------------+------+----------+--------------------------------------------------------+
| id | select_type | table | partitions | type   | possible_keys                              | key                         | key_len | ref                                  | rows | filtered | Extra                                                  |
+----+-------------+-------+------------+--------+--------------------------------------------+-----------------------------+---------+--------------------------------------+------+----------+--------------------------------------------------------+
|  1 | SIMPLE      | user  | NULL       | range  | PRIMARY,web_user_phone_unique_index        | web_user_phone_unique_index | 42      | NULL                                 |    1 |   100.00 | Using index condition; Using temporary; Using filesort |
|  1 | SIMPLE      | orde  | NULL       | ref    | ope_orders_uid,idx_operator_id,idx_user_id | ope_orders_uid              | 4       | bq_bjev_gxqc.user.id                 |    8 |   100.00 | Using where                                            |
|  1 | SIMPLE      | car   | NULL       | eq_ref | PRIMARY                                    | PRIMARY                     | 4       | bq_bjev_gxqc.orde.car_id             |    1 |   100.00 | NULL                                                   |
|  1 | SIMPLE      | ocm   | NULL       | ref    | ope_charge_main_charge_code                | ope_charge_main_charge_code | 8       | bq_bjev_gxqc.orde.charge_stand_encod |    1 |   100.00 | NULL                                                   |
|  1 | SIMPLE      | admin | NULL       | eq_ref | PRIMARY                                    | PRIMARY                     | 4       | bq_bjev_gxqc.orde.update_userid      |    1 |   100.00 | Using index                                            |
|  1 | SIMPLE      | scl   | NULL       | eq_ref | PRIMARY                                    | PRIMARY                     | 8       | bq_bjev_gxqc.orde.coupon_id          |    1 |   100.00 | Using where                                            |
|  1 | SIMPLE      | sct   | NULL       | eq_ref | PRIMARY                                    | PRIMARY                     | 4       | bq_bjev_gxqc.scl.coupon_type_id      |    1 |   100.00 | NULL                                                   |
+----+-------------+-------+------------+--------+--------------------------------------------+-----------------------------+---------+--------------------------------------+------+----------+--------------------------------------------------------+

执行计划改变了,由 user 表作为最开始的驱动表,由上面可知,过滤条件后只剩下 1 条记录。1 条记录去关联ope_orders,这个速度还是很快的。但是 user 表为什么会排序暂时还没研究明白,order by 是在 orde 表上。有大神看到的话,可以互相讨论下。SQL已经优化到0.01秒了,也没有继续再优化下去的必要。

 

四、总结

如果列上面有索引的话,不要在列两端加上% ,类似这种 %aaa%,大部分场景会引起索引失效。aaa% 这种情况也是可以用到索引的,话。

 

posted @ 2018-11-02 09:54  Ziroro  阅读(631)  评论(0编辑  收藏  举报