日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【一起去大厂系列】什么是回表查询?怎么优化回表查询?

發(fā)布時間:2024/2/28 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【一起去大厂系列】什么是回表查询?怎么优化回表查询? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

提到什么是回表查詢之前,不得不先解釋一下InnoDB的索引。

InnoDB的索引

InnoDB有兩大類索引,一類是聚集索引(Clustered Index),一類是普通索引(Secondary Index)

InnoDB聚集索引和普通索引有什么差異?有什么區(qū)別呢?

InnoDB的聚集索引

每行數(shù)據(jù)是存在InnoDB聚集索引的葉子節(jié)點上的,因此InnoDB必須要有且只有一個聚集索引,下面聚集索引的生成規(guī)則:

  • 如果表定義了PK(Primary Key,主鍵),那么PK就是聚集索引。
  • 如果表沒有定義PK,則第一個NOT NULL UNIQUE的列就是聚集索引。
  • 否則InnoDB會另外創(chuàng)建一個隱藏的ROWID作為聚集索引。

這種機制使得基于PK的查詢速度非常快,因為直接定位的行記錄。

InnoDB普通索引

InnoDB普通索引的葉子節(jié)點存儲主鍵值。想拿到行數(shù)據(jù),還得去聚集索引中掃描索引樹。
注意,不是存儲行記錄頭指針,MyISAM的索引葉子節(jié)點存儲記錄指針。


什么是回表查詢

下面舉個例子解釋:
假設(shè)有個表user(id PK,name,code),id是聚集索引,code是普通索引。表中有幾條數(shù)據(jù)。

id name code -----
1 小明 AQ -----
4 小陳 DR -----
7 小紅 CY -----
9 小劉 FP -----
那么兩種索引的B+樹索引就是如下圖這樣:

MySQL中的回表查詢與索引覆蓋:一次百萬級別分頁查詢使用Limit 從90秒到0.6毫秒的優(yōu)化_第1張圖片
從普通索引無法直接定位行記錄,那普通索引的查詢過程是怎么樣的呢?

例: select * from user where code = ‘CY’;

其查詢過程在通常情況下是需要掃描兩遍索引樹的,這里的執(zhí)行過程是這樣的:

如帶色的路徑:

  • 第一遍先通過普通索引定位到主鍵值
  • 然后第二遍再通過聚集索引定位到具體行記錄。

這就是所謂的回表查詢,即先定位主鍵值,再根據(jù)主鍵值定位行記錄,性能相對于只掃描一遍聚集索引樹的性能要低一些。


怎么優(yōu)化回表查詢

那怎么樣解決這個性能低的問題呢?這就涉及到一個概念---------覆蓋索引

覆蓋索引

覆蓋索引就是是一種避免回表查詢的優(yōu)化策略。就是把所有需要查詢的字段都放到普通索引中,這樣普通索引查到的葉子結(jié)點(即上圖中的黑色方框)中已經(jīng)能夠得到所需的所有字段,就不會再去聚集索引中再查詢。

實現(xiàn)覆蓋索引的方式

可分為兩種:

第一種減少查詢字段只查詢縮影有的字段,例如在查詢中,我們只查id字段(也就是主鍵字段),這樣幾百萬條數(shù)據(jù)就不會回表查詢,外層查詢時只有50條數(shù)據(jù)去聚集索引里進行了查詢。又如上面的user表 優(yōu)化sql為不查詢name字段。

例: select id,code from user where code = ‘CY’;

第二種方式就是修改表創(chuàng)建的索引,增加需要查詢的字段,如上面user表,把name也加到索引中,設(shè)置(name,code)兩個字段的聯(lián)合索引 。

覆蓋索引的定義與注意事項

如果一個索引覆蓋(包含)了所有需要查詢的字段的值,這個索引就是覆蓋索引。因為索引中已經(jīng)包含了要查詢的字段的值,因此查詢的時候直接返回索引中的字段值就可以了,不需要再到表中查詢,避免了對主鍵索引的二次查詢,也就提高了查詢的效率。

要注意的是,不是所有類型的索引都可以成為覆蓋索引的。因為覆蓋索引必須要存儲索引的列值,而哈希索引、空間索引和全文索引等都不存儲索引列值,索引MySQL只能使用B-Tree索引做覆蓋索引。

另外,當(dāng)發(fā)起一個被索引覆蓋的查詢(索引覆蓋查詢)時,在explain(執(zhí)行計劃)的Extra列可以看到【Using Index】的信息。

覆蓋索引的優(yōu)點

1.索引條目通常遠小于數(shù)據(jù)行的大小,因為覆蓋索引只需要讀取索引,極大地減少了數(shù)據(jù)的訪問量。

2.索引是按照列值順序存儲的,對于IO密集的范圍查找會比隨機從磁盤讀取每一行數(shù)據(jù)的IO小很多。

3.一些存儲引擎比如MyISAM在內(nèi)存中只緩存索引,數(shù)據(jù)則依賴操作系統(tǒng)來緩存,因此要訪問數(shù)據(jù)的話需要一次系統(tǒng)調(diào)用,使用覆蓋索引則避免了這一點。

4.由于InnoDB的聚簇索引,覆蓋索引對InnoDB引擎下的數(shù)據(jù)庫表特別有用。因為InnoDB的二級索引在葉子節(jié)點中保存了行的主鍵值,如果二級索引能夠覆蓋查詢,就避免了對主鍵索引的二次查詢。

總結(jié)

以上是生活随笔為你收集整理的【一起去大厂系列】什么是回表查询?怎么优化回表查询?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。