在Mysql中使用索引

MySQL查詢的優化是個老生常談的問題,方法更是多種多樣,其中最直接的就是建立索引.html

 

這裏經過一個簡單的demo來實際用一下索引,看看索引在百萬級別查詢中速率的提高效果如何mysql

 

所需數據能夠從我前面的一篇博客中獲取:http://www.javashuo.com/article/p-muuqjoke-bh.htmlsql

 

有一張salaries,app

  查看錶結構以下: 測試

mysql> desc salaries;
+-----------+---------+------+-----+---------+-------+
| Field     | Type    | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no    | int(11) | NO   | PRI | NULL    |       |
| salary    | int(11) | NO   |     | NULL    |       |
| from_date | date    | NO   | PRI | NULL    |       |
| to_date   | date    | NO   |     | NULL    |       |
+-----------+---------+------+-----+---------+-------+

  能夠看到emp_no,from_date都是PRI(主鍵索引),這是在這個表中將這兩個字段聯合起來設置爲主鍵,一張表中仍是隻能有一個主鍵優化

  查看錶的建立命令:spa

  

mysql> show create table salaries;
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                                                                                                                                                                                                       |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| salaries | CREATE TABLE `salaries` (
  `emp_no` int(11) NOT NULL,
  `salary` int(11) NOT NULL,
  `from_date` date NOT NULL,
  `to_date` date NOT NULL,
  PRIMARY KEY (`emp_no`,`from_date`),
  CONSTRAINT `salaries_ibfk_1` FOREIGN KEY (`emp_no`) REFERENCES `employees` (`emp_no`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

   注意我標紅的地方,將emp_no`,`from_date設置爲組合主鍵,組合索引聽從左前綴原則,查詢emp_no,或者查詢(`emp_no`,`from_date`)會走索引,可是查from_date不會走索引,能夠看一下用explain命令查看:code

mysql> explain select * from salaries where emp_no=227694;
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table    | type | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+   
|  1 | SIMPLE      | salaries | ref  | PRIMARY       | PRIMARY | 4       | const |   18 | NULL  |               # key爲PRIMARY 走了索引
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
1 row in set (0.01 sec)

mysql>  explain  select * from salaries where from_date = '1986-06-26';
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | salaries | ALL  | NULL          | NULL | NULL    | NULL | 2838426 | Using where |          key爲Null,Extra 使用了where,沒走索引
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

mysql> explain  select * from salaries where from_date = '1986-06-26' and emp_no=75047;
+----+-------------+----------+-------+---------------+---------+---------+-------------+------+-------+
| id | select_type | table    | type  | possible_keys | key     | key_len | ref         | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+-------------+------+-------+
|  1 | SIMPLE      | salaries | const | PRIMARY       | PRIMARY | 7       | const,const |    1 | NULL  |    # key爲PRIMARY 走了索引
 +----+-------------+----------+-------+---------------+---------+---------+-------------+------+-------+ 
1 row in set (0.00 sec)

 

  to_date字段沒有設置索引,咱們來測試一下加索引先後,該字段查詢效率會不會有提高:htm

  未加索引:blog

  

mysql> select * from salaries where to_date = '1986-06-26';                                                                                                                                          +--------+--------+------------+------------+
| emp_no | salary | from_date  | to_date    |
+--------+--------+------------+------------+
|  25676 |  40000 | 1985-06-26 | 1986-06-26 |
|  28757 |  40000 | 1985-06-26 | 1986-06-26 |
|  30860 |  64620 | 1985-06-26 | 1986-06-26 |
|  69209 |  40000 | 1985-06-26 | 1986-06-26 |
|  80550 |  45292 | 1985-06-26 | 1986-06-26 |
|  91204 |  47553 | 1985-06-26 | 1986-06-26 |
|  96140 |  52908 | 1985-06-26 | 1986-06-26 |
| 208352 |  42989 | 1985-06-26 | 1986-06-26 |
| 213109 |  90133 | 1985-06-26 | 1986-06-26 |
| 217498 |  80247 | 1985-06-26 | 1986-06-26 |
| 219462 |  83880 | 1985-06-26 | 1986-06-26 |
| 223150 |  40000 | 1985-06-26 | 1986-06-26 |
| 227694 |  73897 | 1985-06-26 | 1986-06-26 |
| 232856 |  73126 | 1985-06-26 | 1986-06-26 |
| 237619 |  56982 | 1985-06-26 | 1986-06-26 |
| 244087 |  40000 | 1985-06-26 | 1986-06-26 |
| 253472 |  72004 | 1985-06-26 | 1986-06-26 |
| 257395 |  40000 | 1985-06-26 | 1986-06-26 |
| 261811 |  40000 | 1985-06-26 | 1986-06-26 |
| 268968 |  40000 | 1985-06-26 | 1986-06-26 |
| 269331 |  40000 | 1985-06-26 | 1986-06-26 |
| 274805 |  40000 | 1985-06-26 | 1986-06-26 |
| 279432 |  74530 | 1985-06-26 | 1986-06-26 |
| 285685 |  83198 | 1985-06-26 | 1986-06-26 |
| 286745 |  44082 | 1985-06-26 | 1986-06-26 |
| 290901 |  49876 | 1985-06-26 | 1986-06-26 |
| 400719 |  79168 | 1985-06-26 | 1986-06-26 |
| 401448 |  49600 | 1985-06-26 | 1986-06-26 |
| 427374 |  40000 | 1985-06-26 | 1986-06-26 |
| 432024 |  40000 | 1985-06-26 | 1986-06-26 |
| 432654 |  40000 | 1985-06-26 | 1986-06-26 |
| 438461 |  44451 | 1985-06-26 | 1986-06-26 |
| 446228 |  42733 | 1985-06-26 | 1986-06-26 |
| 447391 |  62381 | 1985-06-26 | 1986-06-26 |
| 448823 |  40000 | 1985-06-26 | 1986-06-26 |
| 452355 |  40000 | 1985-06-26 | 1986-06-26 |
| 453590 |  61615 | 1985-06-26 | 1986-06-26 |
| 456521 |  40000 | 1985-06-26 | 1986-06-26 |
| 464415 |  48955 | 1985-06-26 | 1986-06-26 |
| 467901 |  52349 | 1985-06-26 | 1986-06-26 |
| 472895 |  40000 | 1985-06-26 | 1986-06-26 |
| 476501 |  40000 | 1985-06-26 | 1986-06-26 |
| 477079 |  40000 | 1985-06-26 | 1986-06-26 |
| 478934 |  55054 | 1985-06-26 | 1986-06-26 |
| 480301 |  44177 | 1985-06-26 | 1986-06-26 |
| 484507 |  40000 | 1985-06-26 | 1986-06-26 |
| 486187 |  40000 | 1985-06-26 | 1986-06-26 |
| 491159 |  46034 | 1985-06-26 | 1986-06-26 |
| 493154 |  40000 | 1985-06-26 | 1986-06-26 |
| 498140 |  81909 | 1985-06-26 | 1986-06-26 |
| 498565 |  72853 | 1985-06-26 | 1986-06-26 |
+--------+--------+------------+------------+
51 rows in set (1.08 sec)

  用explain分析一下:

  

mysql> explain select * from salaries where to_date = '1986-06-26';
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | salaries | ALL  | NULL          | NULL | NULL    | NULL | 2838426 | Using where |         # Extra使用where。key爲Null,在2838426條數據中找51條記錄用時1.08s
+----+-------------+----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

  

  爲to_date字段加索引:

mysql> create index to_date on salaries(to_date);
Query OK, 0 rows affected (5.31 sec)
Records: 0  Duplicates: 0  Warnings: 0                                   建立索引會耗時,索然提高了查詢速率,可是更新添加動做會效率下降

 如今看一下表結構:

  

mysql> desc salaries;
+-----------+---------+------+-----+---------+-------+
| Field     | Type    | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| emp_no    | int(11) | NO   | PRI | NULL    |       |
| salary    | int(11) | NO   |     | NULL    |       |
| from_date | date    | NO   | PRI | NULL    |       |
| to_date   | date    | NO   | MUL | NULL    |       |            MUL表示非惟一索引
+-----------+---------+------+-----+---------+-------+
4 rows in set (0.00 sec)

mysql> show create table salaries;
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                                                                                                                                                                                                                                    |
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| salaries | CREATE TABLE `salaries` (
  `emp_no` int(11) NOT NULL,
  `salary` int(11) NOT NULL,
  `from_date` date NOT NULL,
  `to_date` date NOT NULL,
  PRIMARY KEY (`emp_no`,`from_date`),
  KEY `to_date` (`to_date`),                                                                                # 建立了索引key爲to_date
  CONSTRAINT `salaries_ibfk_1` FOREIGN KEY (`emp_no`) REFERENCES `employees` (`emp_no`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

 

   再次查詢:

   

mysql> select * from salaries where to_date = '1986-06-26';
+--------+--------+------------+------------+
| emp_no | salary | from_date  | to_date    |
+--------+--------+------------+------------+
|  25676 |  40000 | 1985-06-26 | 1986-06-26 |
|  28757 |  40000 | 1985-06-26 | 1986-06-26 |
|  30860 |  64620 | 1985-06-26 | 1986-06-26 |
|  69209 |  40000 | 1985-06-26 | 1986-06-26 |
|  80550 |  45292 | 1985-06-26 | 1986-06-26 |
|  91204 |  47553 | 1985-06-26 | 1986-06-26 |
|  96140 |  52908 | 1985-06-26 | 1986-06-26 |
| 208352 |  42989 | 1985-06-26 | 1986-06-26 |
| 213109 |  90133 | 1985-06-26 | 1986-06-26 |
| 217498 |  80247 | 1985-06-26 | 1986-06-26 |
| 219462 |  83880 | 1985-06-26 | 1986-06-26 |
| 223150 |  40000 | 1985-06-26 | 1986-06-26 |
| 227694 |  73897 | 1985-06-26 | 1986-06-26 |
| 232856 |  73126 | 1985-06-26 | 1986-06-26 |
| 237619 |  56982 | 1985-06-26 | 1986-06-26 |
| 244087 |  40000 | 1985-06-26 | 1986-06-26 |
| 253472 |  72004 | 1985-06-26 | 1986-06-26 |
| 257395 |  40000 | 1985-06-26 | 1986-06-26 |
| 261811 |  40000 | 1985-06-26 | 1986-06-26 |
| 268968 |  40000 | 1985-06-26 | 1986-06-26 |
| 269331 |  40000 | 1985-06-26 | 1986-06-26 |
| 274805 |  40000 | 1985-06-26 | 1986-06-26 |
| 279432 |  74530 | 1985-06-26 | 1986-06-26 |
| 285685 |  83198 | 1985-06-26 | 1986-06-26 |
| 286745 |  44082 | 1985-06-26 | 1986-06-26 |
| 290901 |  49876 | 1985-06-26 | 1986-06-26 |
| 400719 |  79168 | 1985-06-26 | 1986-06-26 |
| 401448 |  49600 | 1985-06-26 | 1986-06-26 |
| 427374 |  40000 | 1985-06-26 | 1986-06-26 |
| 432024 |  40000 | 1985-06-26 | 1986-06-26 |
| 432654 |  40000 | 1985-06-26 | 1986-06-26 |
| 438461 |  44451 | 1985-06-26 | 1986-06-26 |
| 446228 |  42733 | 1985-06-26 | 1986-06-26 |
| 447391 |  62381 | 1985-06-26 | 1986-06-26 |
| 448823 |  40000 | 1985-06-26 | 1986-06-26 |
| 452355 |  40000 | 1985-06-26 | 1986-06-26 |
| 453590 |  61615 | 1985-06-26 | 1986-06-26 |
| 456521 |  40000 | 1985-06-26 | 1986-06-26 |
| 464415 |  48955 | 1985-06-26 | 1986-06-26 |
| 467901 |  52349 | 1985-06-26 | 1986-06-26 |
| 472895 |  40000 | 1985-06-26 | 1986-06-26 |
| 476501 |  40000 | 1985-06-26 | 1986-06-26 |
| 477079 |  40000 | 1985-06-26 | 1986-06-26 |
| 478934 |  55054 | 1985-06-26 | 1986-06-26 |
| 480301 |  44177 | 1985-06-26 | 1986-06-26 |
| 484507 |  40000 | 1985-06-26 | 1986-06-26 |
| 486187 |  40000 | 1985-06-26 | 1986-06-26 |
| 491159 |  46034 | 1985-06-26 | 1986-06-26 |
| 493154 |  40000 | 1985-06-26 | 1986-06-26 |
| 498140 |  81909 | 1985-06-26 | 1986-06-26 |
| 498565 |  72853 | 1985-06-26 | 1986-06-26 |
+--------+--------+------------+------------+
51 rows in set (0.00 sec)                                        # 建立索引後一樣的查詢條件從1.08s變爲了0.00s,驚訝吧

  explain分析:

  

mysql> explain select * from salaries where to_date = '1986-06-26';
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table    | type | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | salaries | ref  | to_date       | to_date | 3       | const |   51 | NULL  |       key從Null變味了索引字段to_date,row從兩百多萬變爲了51
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)

 

  這個demo從數據上直觀的體現了索引帶來的查詢效率提高有多可觀,可是索引也是有利必有害,更多索引的底層知識能夠參考這位大牛的博客:http://www.javashuo.com/article/p-ocmahjoq-k.html

相關文章
相關標籤/搜索