MySQL覆蓋索引(Covering Index)

MySQL覆蓋索引(Covering Index)  html

 



mysql高效索引之覆蓋索引

概念 mysql

若是索引包含全部知足查詢須要的數據的索引成爲覆蓋索引(Covering Index),也就是平時所說的不須要回表操做 面試

判斷標準 算法

使用explain,能夠經過輸出的extra列來判斷,對於一個索引覆蓋查詢,顯示爲using index,MySQL查詢優化器在執行查詢前會決定是否有索引覆蓋查詢 sql

 

注意 數據庫

一、覆蓋索引也並不適用於任意的索引類型,索引必須存儲列的值 緩存

二、Hash 和full-text索引不存儲值,所以MySQL只能使用B-TREE 微信

三、而且不一樣的存儲引擎實現覆蓋索引都是不一樣的 網絡

四、並非全部的存儲引擎都支持它們 ide

五、若是要使用覆蓋索引,必定要注意SELECT 列表值取出須要的列,不能夠是SELECT *,由於若是將全部字段一塊兒作索引會致使索引文件過大,查詢性能降低,不能爲了利用覆蓋索引而這麼作

 

InnoDB

一、覆蓋索引查詢時除了除了索引自己的包含的列,還可使用其默認的彙集索引列

二、這跟INNOB的索引結構有關係,主索引是B+樹索引存儲,也即咱們所說的數據行即索引,索引即數據

三、對於INNODB的輔助索引,它的葉子節點存儲的是索引值和指向主鍵索引的位置,而後須要經過主鍵在查詢表的字段值,因此輔助索引存儲了主鍵的值

四、覆蓋索引也能夠用上INNODB 默認的彙集索引

五、     innodb引擎的全部儲存了主鍵ID,事務ID,回滾指針,非主鍵ID,他的查詢就會是非主鍵ID也可覆蓋來取得主鍵ID

 

覆蓋索引是一種很是強大的工具,能大大提升查詢性能,只須要讀取索引而不用讀取數據有如下一些優勢
一、索引項一般比記錄要小,因此MySQL訪問更少的數據
二、索引都按值的大小順序存儲,相對於隨機訪問記錄,須要更少的I/O
三、大多數據引擎能更好的緩存索引,好比MyISAM只緩存索引
四、覆蓋索引對於InnoDB表尤爲有用,由於InnoDB使用匯集索引組織數據,若是二級索引中包含查詢所需的數據,就再也不須要在彙集索引中查找了


在sakila的inventory表中,有一個組合索引(store_id,film_id),對於只須要訪問這兩列的查 詢,MySQL就可使用索引,以下

表結構

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE `inventory` (            
                 `inventory_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,            
                 `film_id` smallint(5) unsigned NOT NULL,            
                 `store_id` tinyint(3) unsigned NOT NULL,            
                 `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,            
                 PRIMARY KEY (`inventory_id`),            
                 KEY `idx_fk_film_id` (`film_id`),            
                 KEY `idx_store_id_film_id` (`store_id`,`film_id`),            
                 CONSTRAINT `fk_inventory_film` FOREIGN KEY (`film_id`) REFERENCES `film` (`film_id`) ON UPDATE CASCADE,            
                 CONSTRAINT `fk_inventory_store` FOREIGN KEY (`store_id`) REFERENCES `store` (`store_id`) ON UPDATE CASCADE            
) ENGINE=InnoDB AUTO_INCREMENT=4582 DEFAULT CHARSET=utf8 |            

 查詢語句

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql>  EXPLAIN SELECT store_id, film_id FROM sakila.inventory\G            
*************************** 1. row ***************************            
                          id: 1            
                 select_type: SIMPLE            
                       table: inventory            
                        type: index            
possible_keys: NULL            
                         key: idx_store_id_film_id            
                     key_len: 3            
                         ref: NULL            
                        rows: 4581            
                       Extra: Using index            
1 row in set (0.03 sec)            

 在大多數引擎中,只有當查詢語句所訪問的列是索引的一部分時,索引纔會覆蓋。可是,InnoDB不限於此,InnoDB的二級索引在葉子節點中存儲了 primary key的值。所以,sakila.actor表使用InnoDB,並且對因而last_name上有索引,因此,索引能覆蓋那些訪問actor_id的查 詢,以下

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> EXPLAIN SELECT actor_id, last_name  FROM sakila.actor WHERE last_name =                'HOPPER'               \G            
*************************** 1. row ***************************            
                          id: 1            
                 select_type: SIMPLE            
                       table: actor            
                        type: ref            
possible_keys: idx_actor_last_name            
                         key: idx_actor_last_name            
                     key_len: 137            
                         ref:                const            
                        rows: 2            
                       Extra: Using where; Using index            
1 row in set (0.00 sec)            

使用索引進行排序

MySQL中,有兩種方式生成有序結果集:一是使用filesort,二是按索引順序掃描

利用索引進行排序操做是很是快的,並且能夠利用同一索引同時進 行查找和排序操做。當索引的順序與ORDER BY中的列順序相同且全部的列是同一方向(所有升序或者所有降序)時,可使用索引來排序,若是查詢是鏈接多個表,僅當ORDER BY中的全部列都是第一個表的列時纔會使用索引,其它狀況都會使用filesort

1
2
3
4
5
6
7
8
CREATE TABLE `actor` (            
                 `actor_id` int(10) unsigned NOT NULL AUTO_INCREMENT,            
                 `name` varchar(16) NOT NULL DEFAULT                ''               ,            
                 `password` varchar(16) NOT NULL DEFAULT                ''               ,            
                 PRIMARY KEY (`actor_id`),            
                 KEY `name` (`name`)            
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;            
insert into actor(name,password) values (               'cat01'               ,               '1234567'               ),(               'cat02'               ,               '1234567'               ),(               'ddddd'               ,               '1234567'               ),(               'aaaaa'               ,               '1234567'               );            

一、 explain select actor_id from actor order by actor_id \G

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select actor_id from actor order by actor_id \G            
*************************** 1. row ***************************            
                          id: 1            
                 select_type: SIMPLE            
                       table: actor            
                        type: index            
possible_keys: NULL            
                         key: PRIMARY            
                     key_len: 4            
                         ref: NULL            
                        rows: 4            
                       Extra: Using index            
1 row in set (0.00 sec)            

 二、explain select actor_id from actor order by password \G

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select actor_id from actor order by password \G            
*************************** 1. row ***************************            
                          id: 1            
                 select_type: SIMPLE            
                       table: actor            
                        type: ALL            
possible_keys: NULL            
                         key: NULL            
                     key_len: NULL            
                         ref: NULL            
                        rows: 4            
                       Extra: Using filesort            
1 row in set (0.00 sec)            

 三、explain select actor_id from actor order by name \G

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> explain select actor_id from actor order by name \G            
*************************** 1. row ***************************            
                          id: 1            
                 select_type: SIMPLE            
                       table: actor            
                        type: index            
possible_keys: NULL            
                         key: name            
                     key_len: 50            
                         ref: NULL            
                        rows: 4            
                       Extra: Using index            
1 row in set (0.00 sec)            

 

當MySQL不能使用索引進行排序時,就會利用本身的排序算法(快速排序算法)在內存(sort buffer)中對數據進行排序,若是內存裝載不下,它會將磁盤上的數據進行分塊,再對各個數據塊進行排序,而後將各個塊合併成有序的結果集(實際上就是外排序)

對於filesort,MySQL有兩種排序算法

一、兩遍掃描算法(Two passes)

實現方式是先將需要排序的字段和能夠直接定位到相關行數據的指針信息取出,而後在設定的內存(經過參數sort_buffer_size設定)中進行排序,完成排序以後再次經過行指針信息取出所需的Columns
注:該算法是4.1以前採用的算法,它須要兩次訪問數據,尤爲是第二次讀取操做會致使大量的隨機I/O操做。另外一方面,內存開銷較小


二、 一次掃描算法(single pass)

該算法一次性將所需的Columns所有取出,在內存中排序後直接將結果輸出
注: 從 MySQL 4.1 版本開始使用該算法。它減小了I/O的次數,效率較高,可是內存開銷也較大。若是咱們將並不須要的Columns也取出來,就會極大地浪費排序過程所須要 的內存。在 MySQL 4.1 以後的版本中,能夠經過設置 max_length_for_sort_data 參數來控制 MySQL 選擇第一種排序算法仍是第二種。當取出的全部大字段總大小大於 max_length_for_sort_data 的設置時,MySQL 就會選擇使用第一種排序算法,反之,則會選擇第二種。爲了儘量地提升排序性能,咱們天然更但願使用第二種排序算法,因此在 Query 中僅僅取出須要的 Columns 是很是有必要的。

當對鏈接操做進行排序時,若是ORDER BY僅僅引用第一個表的列,MySQL對該表進行filesort操做,而後進行鏈接處理,此時,EXPLAIN輸出「Using filesort」;不然,MySQL必須將查詢的結果集生成一個臨時表,在鏈接完成以後進行filesort操做,此時,EXPLAIN輸出 「Using temporary;Using filesort」

理解MySQL數據庫覆蓋索引

話說有這麼一個表:

CREATE TABLE `user_group` (       
  `id` int(11) NOT NULL auto_increment,       
  `uid` int(11) NOT NULL,       
  `group_id` int(11) NOT NULL,       
  PRIMARY KEY  (`id`),       
  KEY `uid` (`uid`),       
  KEY `group_id` (`group_id`),       
) ENGINE=InnoDB AUTO_INCREMENT=750366 DEFAULT CHARSET=utf8      
     

看AUTO_INCREMENT就知道數據並很少,75萬條。而後是一條簡單的查詢:

 

SELECT SQL_NO_CACHE uid FROM user_group WHERE group_id = 245;

 

很簡單對不對?怪異的地方在於:

  若是換成MyISAM作存儲引擎的時候,查詢耗時只須要0.01s,用InnoDB卻會是0.15s左右

  若是隻是就這麼點差距其實不是什麼大不了的事,可是真實的業務需求比這個複雜,形成的差距也很大:MyISAM只須要0.12s,InnoDB則須要2.2s.,最終定位到問題癥結是在這條SQL。

  Explain的結果是:

+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+ 
| id | select_type | table      | type | possible_keys | key      | key_len | ref   | rows | Extra | 
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+ 
|  1 | SIMPLE      | user_group | ref  | group_id      | group_id | 4       | const | 5544 |       | 
+----+-------------+------------+------+---------------+----------+---------+-------+------+-------+

看起來已經用上索引了,而這條SQL語句已經簡單到讓我沒法再優化了。最後請前同事Gaston診斷了一下,他認爲:數據分佈上,group_id相同的比較多,uid散列的比較均勻,加索引的效果通常,可是仍是建議我試着加了一個多列索引:

 

ALTER TABLE user_group ADD INDEX group_id_uid (group_id, uid);

 

 

 

 

而後,難以想象的事情發生了……這句SQL查詢的性能發生了巨大的提高,竟然已經能夠跑到0.00s左右了。通過優化的SQL再結合真實的業務需求,也從以前2.2s降低到0.05s。

再Explain一次:

+----+-------------+------------+------+-----------------------+--------------+---------+-------+------+-------------+ 
| id | select_type | table      | type | possible_keys         | key          | key_len | ref   | rows | Extra       | 
+----+-------------+------------+------+-----------------------+--------------+---------+-------+------+-------------+ 
|  1 | SIMPLE      | user_group | ref  | group_id,group_id_uid | group_id_uid | 4       | const | 5378 | Using index | 
+----+-------------+------------+------+-----------------------+--------------+---------+-------+------+-------------+

原來是這種叫覆蓋索引(covering index),MySQL只須要經過索引就能夠返回查詢所須要的數據,而沒必要在查到索引以後再去查詢數據,因此那是至關的快!!可是同時也要求所查詢的字段必須被索引所覆蓋到,在Explain的時候,輸出的Extra信息中若是有「Using Index」,就表示這條查詢使用了覆蓋索引。

 
 
 不用覆蓋索引的狀況下,mysql的存儲引擎Myisam要比innodb查詢速度快的緣由是,這二者的數據存儲方式不同,myisan是順序存儲,而innodb聚簇索引,myisam的索引指針指向的直接就是數據的的屋裏地址,而innodb的索引指向的是主鍵,因此須要進行二次查找(sql用到索引時將會是行鎖,鎖的粒度小),下降了查詢的效率,所以innodb引入了索引覆蓋技術,提升查找的效率  
 
 




 

本文主要概述MySQL的覆蓋索引,以及幾種常見的優化場景



內容概要

   




  •  彙集索引和輔助索引
  •  什麼是覆蓋索引
  •  幾種優化場景  
  •  整體建議




彙集索引和輔助索引

  • 彙集索引(主鍵索引)

—innodb存儲引擎是索引組織表,即表中的數據按照主鍵順序存放。而彙集索引就是按照每張表的主鍵構造一顆B+樹,同時葉子節點中存放的即爲整張表的記錄數據  

—彙集索引的葉子節點稱爲數據頁,數據頁,數據頁!重要的事說三遍。彙集索引的這個特性決定了索引組織表中的數據也是索引的一部分。  

  • 輔助索引(二級索引)

—非主鍵索引  

—葉子節點=鍵值+書籤。Innodb存儲引擎的書籤就是相應行數據的主鍵索引值  


輔助索引檢索數據圖示以下  

02e814446da64610faadb2047447dac00bf1241e

因爲檢索數據時,老是先獲取到書籤值(主鍵值),再返回查詢,所以輔助索引也被稱之爲二級索引  


什麼是覆蓋索引

  覆蓋索引(covering index)指一個查詢語句的執行只須要從輔助索引中就能夠獲得查詢記錄,而不須要查詢彙集索引中的記錄。也能夠稱之爲實現了 索引覆蓋。  

  那麼,優勢顯而易見。輔助索引不包含一整行的記錄,所以能夠大大減小IO操做。覆蓋索引是mysql dba經常使用的一種SQL優化手段  


先看一個簡單示例  

f9f63889fcd0c60d5f837b1e0a633e8ad4b903a5

從執行計劃看到,這個SQL語句只經過索引,就取到了所須要的數據,這個過程,就稱爲索引覆蓋  


幾種優化場景

一、無where條件的查詢優化

以下這個查詢  

5c0aee6dcacf2845c0b2824b5d2b808fe65daa95

執行計劃中,type爲ALL,表明進行了全表掃描,掃描的行數也與表的行數一致  


如何改進?優化措施很簡單,就是對這個查詢列創建索引。以下,  

mysql> alter table t1 add key(staff_id);

 
咱們再看一下優化以後的效果  

  • 執行計劃
mysql> explain select sql_no_cache count(staff_id) from t1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: index
possible_keys: NULL
          key: staff_id
      key_len: 1
          ref: NULL
         rows: 1023849

1 row in set (0.00 sec)

  Using index表示使用到了索引  

  • 查詢消耗

80af484e7e92311c289f0a473c6f684fb244effc

從時間消耗上來看,才100W的數據,已經有了比較明顯的差異了  


執行計劃解讀以下:  

Possible_keys爲null,說明沒有where條件時優化器沒法經過索引檢索數據;  

可是這裏使用了索引的另一個優勢,即從索引中獲取數據,減小了讀取的數據塊的數量  

   

  無where條件的查詢,能夠經過索引來實現索引覆蓋查詢,但前提條件是,查詢返回的字段數足夠少,更不用說select *之類的了。畢竟,創建key length過長的索引,始終不是一件好事情。  

二、二次檢索優化

以下這個查詢,  

mysql> select sql_no_cache rental_date from t1 where inventory_id<80000;
…
…
| 2005-08-23 15:08:00 |
| 2005-08-23 15:09:17 |
| 2005-08-23 15:10:42 |
| 2005-08-23 15:15:02 |
| 2005-08-23 15:15:19 |
| 2005-08-23 15:16:32 |
+---------------------+
79999 rows in set (0.13 sec)

 
執行計劃:  

mysql> explain select sql_no_cache rental_date from t1 where inventory_id<80000\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: range
possible_keys: inventory_id
          key: inventory_id
      key_len: 3
          ref: NULL
         rows: 153734
        Extra: Using index condition
1 row in set (0.00 sec)

 
  從執行計劃,咱們看到,這個SQL實際上是使用到了索引的,雖然查詢的數據量很大,可是相對比全表掃描的性能消耗,優化器仍是選擇了索引。  


更優的改進措施?  

  從上面執行計劃中,咱們發現Extra信息爲Using index condition而不是Using index,這說明,使用的檢索方式爲二級檢索,即79999個書籤值被用來進行回表查詢。可想而知,仍是會有必定的性能消耗的  


嘗試針對這個SQL創建聯合索引,以下  

mysql> alter table t1 add key(inventory_id,rental_date);

 
  這個聯合索引前置列爲where子句的檢索字段,第二個字段爲查詢返回的字段。下面來看下效果如何。  


爲避免優化器對索引的選擇出現誤差,咱們首先收集一下統計信息  

mysql> analyze table t1\G
*************************** 1. row ***************************
   Table: sakila.t1
      Op: analyze
Msg_type: status
Msg_text: OK
1 row in set (0.03 sec)

 
執行計劃  

mysql> explain select sql_no_cache rental_date from t1 where inventory_id<80000\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: range
possible_keys: inventory_id,inventory_id_2
          key: inventory_id_2
      key_len: 3
          ref: NULL
         rows: 162884
        
1 row in set (0.00 sec)

 

  一樣是使用索引,但這裏的提示信息爲Using index而不是Using index condition。這表明沒有了回表查詢的過程,也就是實現了索引覆蓋  


查詢消耗  

mysql> select sql_no_cache rental_date from t1 where inventory_id<80000;
…
…
| 2005-08-23 15:08:00 |
| 2005-08-23 15:09:17 |
| 2005-08-23 15:10:42 |
| 2005-08-23 15:15:02 |
| 2005-08-23 15:15:19 |
| 2005-08-23 15:16:32 |
+---------------------+
79999 rows in set (0.09 sec)

    從執行時間上來看,快了大約40ms,雖然只有40ms,但在實際的生產環境下,卻可能會因系統的整體負載被無限放大。  

  和前面場景限制相似,當where條件與查詢字段總數較少的狀況下,使用這種優化建議,是個不錯的選擇。  

三、分頁查詢優化

  分頁查詢的優化,相信大部分的DBA同窗都碰到過,一般比較常規的優化手段就是查詢改寫,這裏主要介紹一下新的思路,就是經過索引覆蓋來優化  


以下這個查詢場景  

mysql> select tid,return_date from t1 order by inventory_id limit 50000,10;
+-------+---------------------+
| tid   | return_date         |
+-------+---------------------+
| 50001 | 2005-06-17 23:04:36 |
| 50002 | 2005-06-23 03:16:12 |
| 50003 | 2005-06-20 22:41:03 |
| 50004 | 2005-06-23 04:39:28 |
| 50005 | 2005-06-24 04:41:20 |
| 50006 | 2005-06-22 22:54:10 |
| 50007 | 2005-06-18 07:21:51 |
| 50008 | 2005-06-25 21:51:16 |
| 50009 | 2005-06-21 03:44:32 |
| 50010 | 2005-06-19 00:00:34 |
+-------+---------------------+
10 rows in set (0.75 sec)

 
在未優化以前,咱們看到它的執行計劃是如此的糟糕  

mysql> explain select tid,return_date from t1 order by inventory_id limit 50000,10\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1023675
        
1 row in set (0.00 sec)

  全表掃描,加上額外的排序,相信產生的性能消耗是不低的  

如何經過覆蓋索引優化呢?  

 咱們建立一個索引,包含排序列以及返回列,因爲tid是主鍵字段,所以,下面的複合索引就包含了tid的字段值  

mysql> alter table t1 add index liu(inventory_id,return_date);
Query OK, 0 rows affected (3.11 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> analyze table t1\G
*************************** 1. row ***************************
   Table: sakila.t1
      Op: analyze
Msg_type: status
Msg_text: OK
1 row in set (0.04 sec)

 


那麼,效果如何呢?  


mysql> select tid,return_date from t1 order by inventory_id limit 50000,10;
+-------+---------------------+
| tid   | return_date         |
+-------+---------------------+
| 50001 | 2005-06-17 23:04:36 |
| 50002 | 2005-06-23 03:16:12 |
| 50003 | 2005-06-20 22:41:03 |
| 50004 | 2005-06-23 04:39:28 |
| 50005 | 2005-06-24 04:41:20 |
| 50006 | 2005-06-22 22:54:10 |
| 50007 | 2005-06-18 07:21:51 |
| 50008 | 2005-06-25 21:51:16 |
| 50009 | 2005-06-21 03:44:32 |
| 50010 | 2005-06-19 00:00:34 |
+-------+---------------------+
10 rows in set (0.03 sec)

 

能夠發現,添加複合索引後,速度提高0.7s!  


咱們看一下改進後的執行計劃  

mysql> explain select tid,return_date from t1 order by inventory_id limit 50000,10\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
         type: index
possible_keys: NULL
          key: liu
      key_len: 9
          ref: NULL
         rows: 50010
        
1 row in set (0.00 sec)

執行計劃也能夠看到,使用到了複合索引,而且不須要回表


接下來,咱們對比一下,索引覆蓋與常規優化手段的效果差別  



爲了讓結果更明顯,我將查詢修改成 limit 800000,10  


如今看一下,經過覆蓋索引查詢的性能消耗  

mysql> select tid,return_date from t1 order by inventory_id limit 800000,10;
+--------+---------------------+
| tid    | return_date         |
+--------+---------------------+
| 800001 | 2005-08-24 13:09:34 |
| 800002 | 2005-08-27 11:41:03 |
| 800003 | 2005-08-22 18:10:22 |
| 800004 | 2005-08-22 16:47:23 |
| 800005 | 2005-08-26 20:32:02 |
| 800006 | 2005-08-21 14:55:42 |
| 800007 | 2005-08-28 14:45:55 |
| 800008 | 2005-08-29 12:37:32 |
| 800009 | 2005-08-24 10:38:06 |
| 800010 | 2005-08-23 12:10:57 |
+--------+---------------------+

 
與之對比的是以下改寫SQL方式  


改寫後的sql以下,思想是經過索引消除排序  

select a.tid,a.return_date from  t1 a 
inner join 
(select tid from t1 order by  inventory_id limit 800000,10) b on a.tid=b.tid;


並在此基礎上,咱們爲inventory_id列建立索引,並刪除以前的覆蓋索引  

mysql> alter table t1 add index idx_inid(inventory_id),drop index liu;

而後收集統計信息。


查詢消耗以下

mysql> select a.tid,a.return_date from  t1 a inner join  (select tid from t1 order by  inventory_id limit 800000,10) b on a.tid=b.tid;
+--------+---------------------+
| tid    | return_date         |
+--------+---------------------+
| 800001 | 2005-08-24 13:09:34 |
| 800002 | 2005-08-27 11:41:03 |
| 800003 | 2005-08-22 18:10:22 |
| 800004 | 2005-08-22 16:47:23 |
| 800005 | 2005-08-26 20:32:02 |
| 800006 | 2005-08-21 14:55:42 |
| 800007 | 2005-08-28 14:45:55 |
| 800008 | 2005-08-29 12:37:32 |
| 800009 | 2005-08-24 10:38:06 |
| 800010 | 2005-08-23 12:10:57 |
+--------+---------------------+

  能夠看到,這種優化手段較前者時間消耗多了大約140ms。  

  這種優化手段雖然使用索引消除了排序,可是仍是要經過主鍵值回表查詢。所以,在select返回列較少或列寬較小的時候,咱們能夠經過創建複合索引的方式優化分頁查詢,效果更佳,由於它不須要回表!


整體建議

索引具備如下兩大用處:  

一、經過索引檢索僅須要數據  

二、從索引中直接獲取查詢結果  


覆蓋索引的優點,就是利用到索引的第二大用處,在某些場景下,具備意想不到的優化效果。我的總結以下:  

  • Select查詢的返回列包含在索引列中
  • 有where條件時,where條件中要包含索引列或複合索引的前導列
  • 查詢結果的總字段長度能夠接受

from: https://yq.aliyun.com/articles/62419

 
 



mysql延遲查詢, 覆蓋索引使用例子

引用自 'mysql高性能' 5.3.6章節



 

 

不能使用覆蓋索引的狀況 : 



 

解決辦法 : 



 


 
 
 
 





About Me

.............................................................................................................................................

● 本文整理自網絡,如有侵權請聯繫小麥苗刪除

● 本文在itpub(http://blog.itpub.net/26736162/abstract/1/)、博客園(http://www.cnblogs.com/lhrbest)和我的微信公衆號(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/

● 本文博客園地址:http://www.cnblogs.com/lhrbest

● 本文pdf版、我的簡介及小麥苗雲盤地址:http://blog.itpub.net/26736162/viewspace-1624453/

● 數據庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/

● DBA寶典今日頭條號地址:http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826

.............................................................................................................................................

● QQ羣號:230161599(滿)、618766405

● 微信羣:可加我微信,我拉你們進羣,非誠勿擾

● 聯繫我請加QQ好友646634621,註明添加原因

● 於 2017-08-01 09:00 ~ 2017-08-31 22:00 在魔都完成

● 文章內容來源於小麥苗的學習筆記,部分整理自網絡,如有侵權或不當之處還請諒解

● 版權全部,歡迎分享本文,轉載請保留出處

.............................................................................................................................................

小麥苗的微店https://weidian.com/s/793741433?wfr=c&ifr=shopdetail

小麥苗出版的數據庫類叢書http://blog.itpub.net/26736162/viewspace-2142121/

.............................................................................................................................................

使用微信客戶端掃描下面的二維碼來關注小麥苗的微信公衆號(xiaomaimiaolhr)及QQ羣(DBA寶典),學習最實用的數據庫技術。

   小麥苗的微信公衆號      小麥苗的DBA寶典QQ羣1     小麥苗的DBA寶典QQ羣2        小麥苗的微店

.............................................................................................................................................

ico_mailme_02.png
DBA筆試面試講解羣1
DBA筆試面試講解羣2
歡迎與我聯繫




來自 「 ITPUB博客 」 ,連接:http://blog.itpub.net/26736162/viewspace-2144269/,如需轉載,請註明出處,不然將追究法律責任。

相關文章
相關標籤/搜索