背景:手動製造了一張百萬級別的表,根據時間篩選做個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秒,優化效果是不是很明顯呢?
最近開始優化各種查詢效率,更多的優化查詢都會分享出來和大家一起學習!