mysql查詢優化實戰一(合理使用索引)

背景:手動製造了一張百萬級別的表,根據時間篩選做個sum統計。由於不合理的索引設計,導致之前查詢時間爲9s,經過索引優化後只需100ms,下面就是見證奇蹟的時刻!

這次優化的是一張report表,表裏面有百萬數據量。

1、查看錶結構:

mysql> desc report;
+---------------+----------------------+------+-----+---------+-------+
| Field         | Type                 | Null | Key | Default | Extra |
+---------------+----------------------+------+-----+---------+-------+
| date          | date                 | NO   |     | NULL    |       |
| hour          | smallint(6) unsigned | NO   |     | NULL    |       |
| app           | varchar(32)          | YES  |     | NULL    |       |
| name          | varchar(32)          | YES  | MUL | NULL    |       |
| request_num   | bigint(15) unsigned  | NO   |     | 0       |       |
+---------------+----------------------+------+-----+---------+-------+
13 rows in set (0.01 sec)

 

2、查看目前表中的索引:

目前該表的索引名稱是index_date_app,這是一個聯合索引。

mysql> show index from report;
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| report |          1 | index_date_app |            1 | name        | A         |          22 |     NULL | NULL   | YES  | BTREE      |         |               |
| report |          1 | index_date_app |            2 | app         | A         |         299 |     NULL | NULL   | YES  | BTREE      |         |               |
| report |          1 | index_date_app |            3 | date        | A         |       36505 |     NULL | NULL   |      | BTREE      |         |               |
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

3、使用優化前的代碼查看執行計劃:

  通過查看執行計劃發現:我們的索引已經發生效了。

 

    -> SELECT
    ->  name,
    -> sum(request_num) request_num
    -> FROM report
    -> WHERE 1=1
    -> AND date >= '2019-09-05'
    -> AND date <= '2019-09-11'
    -> AND name IN ('ccc','tdd')
    -> GROUP BY  name;
+----+-------------+--------+------------+-------+----------------+----------------+---------+------+---------+----------+-------------+
| id | select_type | table  | partitions | type  | possible_keys  | key            | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+--------+------------+-------+----------------+----------------+---------+------+---------+----------+-------------+
|  1 | SIMPLE      | report | NULL       | index | index_date_app | index_date_app | 201     | NULL | 1174157 |    11.11 | Using where |
+----+-------------+--------+------------+-------+----------------+----------------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

4、查看執行的效率

mysql> SELECT
    ->  name,
    ->  sum(request_num) request_num
    -> FROM report
    -> WHERE 1=1
    -> AND date >= '2019-09-05'
    -> AND date <= '2019-09-11'
    -> AND name IN ('ccc','tdd')
    -> GROUP BY name;
+----------+-------------+
| pmp_name | request_num |
+----------+-------------+
| tdd      |    73660911 |
+----------+-------------+
1 row in set (9.26 sec)

實驗發現:依然執行了9秒鐘,百萬級別的表還不加其他join已經執行的很慢了,因此需要優化索引;

那麼查詢慢的原因是什麼呢?

通過之前幾篇博客內容提到過聯合索引最左匹配的原則(如果不清楚,建議看看基礎,點我),咱們聯合索引的順序是name,app,date;但咱們查詢條件裏面是date以及name,並沒有app,因此,根據最走匹配原則,咱們這次查詢只使用到了name上的索引,並沒有使用用到date索引,爲此查詢的速度很慢。那現在調整索引順序:date,name,app,這樣查詢的時候,就會使用(date,name)聯合索引,查詢效率肯定提升,來,再試一把!

 

mysql> alter table report drop index index_date_app;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table report add index index_date_app(date,pmp_name,app);
Query OK, 0 rows affected (2.97 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show index from report;
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table  | Non_unique | Key_name       | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| report |          1 | index_date_app |            1 | date        | A         |         512 |     NULL | NULL   |      | BTREE      |         |               |
| report |          1 | index_date_app |            2 |     name    | A         |        3018 |     NULL | NULL   | YES  | BTREE      |         |               |
| report |          1 | index_date_app |            3 | app         | A         |       42369 |     NULL | NULL   | YES  | BTREE      |         |               |
+--------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

 

5、索引優化後查看查詢所需要的時間

mysql> SELECT
    -> name,
    ->  sum(request_num) request_num
    -> FROM report
    -> WHERE 1=1
    -> AND date >= '2019-09-05'
    -> AND date <= '2019-09-11'
    -> AND binary pmp_name IN ('ccc','tdd')
    -> GROUP BY  pmp_name;
+----------+-------------+
| pmp_name | request_num |
+----------+-------------+
| tdd      |    73660911 |
+----------+-------------+
1 row in set (0.01 sec)

經過查詢優化後,咱們發現,查詢出來時間只需要0.01s,之前查詢時間是9秒,優化效果是不是很明顯呢?

最近開始優化各種查詢效率,更多的優化查詢都會分享出來和大家一起學習!

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章