深入理解InnoDB(8)—單表訪問

1. 訪問方法

MySQL把執行查詢語句的方式稱之為訪問方法或者訪問類型。
而訪問方法大致分為兩類

  1. 全表掃描
  2. 索引
    而進行細分的話可以分為以下幾類
    (為了方便說明,先建一個表)
CREATE TABLE single_table (id INT NOT NULL AUTO_INCREMENT,key1 VARCHAR(100),key2 INT,key3 VARCHAR(100),key_part1 VARCHAR(100),key_part2 VARCHAR(100),key_part3 VARCHAR(100),common_field VARCHAR(100),PRIMARY KEY (id),KEY idx_key1 (key1),UNIQUE KEY idx_key2 (key2),KEY idx_key3 (key3),KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;

1.1 const

SELECT * FROM single_table WHERE id = 1438;SELECT * FROM single_table WHERE key2 = 3841;

例如上面兩個sql語句,條件都是主鍵或者唯一二級索引列與常量進行比較

  • 第一個sql語句的執行,直接就是在主鍵的聚簇索引中,根據主鍵值進行匹配
  • 第二個sql語句,先要在對應的唯一二級索引中,根據查詢的索引列進行一次匹配,查到主鍵id后,再回表查出所有的數據
    因為主鍵和唯一二級索引,他們的索引列都是唯一的,因此查找的速度是非常快的,所以這種訪問方法叫const,意思就是常數級別的查詢速度.(注意:當索引列的查詢條件為空時,訪問方法并不能算const,因為可能有多條記錄為空)

1.2 ref

而ref的訪問方式類似于唯一二級索引的訪問方式,都是先在二級索引上進行匹配,找到主鍵id后,再回表查詢。但是,因為普通二級索引列的值并不是唯一的,因此可能查詢到的是多條記錄,再進行多次回表。

SELECT * FROM single_table WHERE key1 = 'abc';

例如上面的sql語句,因為key1是普通二級索引,可能存在多個key1='abc’的記錄,因此在查詢時,需要對多個記錄進行回表

1.3 ref_or_null

這個與ref類似,只是多了對于空值的匹配

SELECT * FROM single_table WHERE key1 = 'abc' OR key1 IS NULL;

例如上面的sql語句,是在key1這個二級索引上,查詢key1 = 'abc’和key1為空的主鍵id,然后再進行回表

1.4 range

而range訪問方法,意思就是根據范圍進行查詢,前面的查詢都是匹配單個常數值的,而range是查詢一個范圍的。

SELECT * FROM single_table WHERE key2 IN (1438, 6328) OR (key2 >= 38 AND key2 <= 79);

例如上面的sql語句,只是在之前查詢key2 IN (1438, 6328)的基礎上,將滿足79>=key2>=38的主鍵id也找出來,同樣進行回表

1.5 index

SELECT key_part1, key_part2, key_part3 FROM single_table WHERE key_part2 = 'abc';

key_part2 = 'abc’這個條件并不滿足最左匹配,但是key_part1, key_part2, key_part3 屬于一個聯合索引idx_key_part,因此這個查詢是在idx_key_part索引的葉子節點中,一個一個匹配key_part2 = ‘abc’,直接返回索引列即可,并不需要回表。

index的意思就是直接在索引中匹配查詢。

1.6 all

而all就是全表掃描

2.注意事項

2.1 一般情況下只能利用單個二級索引執行查詢

SELECT * FROM single_table WHERE key1 = 'abc' AND key2 > 1000;

查詢優化器會根據single_table表的統計數據,判斷key1 = ‘abc’ 和 key2 > 1000兩個條件,哪個索引查詢的條數少,就選擇到哪個索引的B+樹上查。

例如在上面的例子中,優化器選擇的是key1 = ‘abc’,那么查詢到滿足key1 = ‘abc’ 的主鍵后,就會回表查詢,并且以 key2 > 1000為條件進行過濾

2.2 明確range訪問方法使用的范圍區間

2.2.1 所有搜索條件都可以使用某個索引的情況

例如:

SELECT * FROM single_table WHERE key2 > 100 AND key2 > 200;

因為條件都是來自同一個索引的范圍查詢,因此只要將對應的范圍進行集合的運算即可

2.2.2 有的搜索條件無法使用索引的情況

SELECT * FROM single_table WHERE key2 > 100 AND common_field = 'abc';

因為common_field = 'abc’無法使用到索引,因此范圍搜索只需要關注key2 > 100這個范圍即可,回表的時候再根據common_field = 'abc’過濾一次,就可以保證選出來的記錄滿足 key2 > 100 AND common_field = ‘abc’。

SELECT * FROM single_table WHERE key2 > 100 OR common_field = 'abc';

但是,當條件換成or以后,就無法使用key2的索引了,因為查詢出了key2 > 100的記錄以后,沒有辦法也在key2的索引中查出common_field = 'abc’的記錄

2.2.3 復雜搜索條件下找出范圍匹配的區間

SELECT * FROM single_table WHERE (key1 > 'xyz' AND key2 = 748 ) OR(key1 < 'abc' AND key1 > 'lmn') OR(key1 LIKE '%suf' AND key1 > 'zzz' AND (key2 < 8000 OR common_field = 'abc')) ;

主要使用到key1和key2 兩個索引,因此對他們進行分別的查找的區間

  • 對于key1
  1. 先將不屬于key1的條件替換為true
(key1 > 'xyz' AND TRUE ) OR
(key1 < 'abc' AND key1 > 'lmn') OR
(TRUE AND key1 > 'zzz' AND (TRUE OR TRUE))
  1. 替換掉永遠為TRUE或FALSE的條件
    因為符合key1 < ‘abc’ AND key1 > 'lmn’永遠為FALSE,所以上邊的搜索條件可以被寫成這樣:
(key1 > 'xyz') OR (key1 > 'zzz')
  1. 合并范圍
key1 > xyz
  • 對于key2
  1. 先將不屬于key1的條件替換為true
(TRUE AND key2 = 748 ) OR
(TRUE AND TRUE) OR
(TRUE AND TRUE AND (key2 < 8000 OR TRUE))
  1. 再次化簡,可以推出最后條件是true,也就是說需要搜索全部的key2索引

2.3 索引合并

之前第一點注意事項說過: 一般情況下只能利用單個二級索引執行查詢,而在特殊情況下也可能在一個查詢中使用到多個二級索引。因此把這種使用到多個索引來完成一次查詢的執行方法稱之為:index merge,具體的索引合并算法有下邊三種。

2.3.1 Intersection合并

Intersection(交集),意味著對多個二級索引的結果找交集

SELECT * FROM single_table WHERE key1 = 'a' AND key3 = 'b';

執行過程

  1. 在key1這個二級索引上找key1 = ‘a’
  2. 在key3這個二級索引中找key3 = ‘b’
  3. 因為二級索引查出來的記錄格式是索引列加主鍵,因此直接對他們查出來的主鍵作一個交集再回表即可

為什么不直接查到二級索引key1的記錄,然后在回表的過程中,過濾掉不滿足key3的條件呢?

因為如果在key1上面查出來的記錄條數很多的話,那么就要進行很多次的回表,而這種回表屬于隨機I/O,非常耗時,而選擇兩次的二級索引查找,屬于順序I/O,有更好的性能。

使用Intersection的情況:

  1. 二級索引只能是等值匹配
SELECT * FROM single_table WHERE key1 = 'a' AND key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c';
SELECT * FROM single_table WHERE key1 > 'a' AND key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c';
SELECT * FROM single_table WHERE key1 = 'a' AND key_part1 = 'a';
  • 第一條sql語句可以正常使用
  • 第二條使用了范圍查詢
  • 第三條沒有使用聯合索引的所有列
  1. 主鍵列可以是范圍匹配
SELECT * FROM single_table WHERE id > 100 AND key1 = 'a';

因為二級索引下,索引列是已經排好序的了,而如果出現了索引列全部相同的記錄,那么將按照主鍵值進行排序,而使用了排好序的主鍵來求交集,就非常簡單了,因為對于兩個已經排好序的主鍵序列,求他們交集的時間復雜度是o(n)。

這也回答了第一種情況,為什么只能是等值匹配,因為只有等值匹配的情況下,索引列記錄相同的幾條記錄才能按照主鍵的順序排好。

上面的兩種情況只是使用Intersection的必要條件。優化器只有在單獨根據搜索條件從某個二級索引中獲取的記錄數太多,導致回表開銷太大,而通過Intersection索引合并后需要回表的記錄數大大減少時才會使用Intersection索引合并。

2.3.2 Union合并

Union是并集的意思,適用于使用不同索引的搜索條件之間使用OR連接起來的情況。
使用Union的情況:

  1. 二級索引只能是等值匹配(與Intersection相同)

  2. 主鍵列可以是范圍匹配(與Intersection相同)

  3. 使用Intersection索引合并的搜索條件
    例如:

SELECT * FROM single_table WHERE key_part1 = 'a' AND key_part2 = 'b' AND key_part3 = 'c' OR (key1 = 'a' AND key3 = 'b');

1.先按key1 = ‘a’ AND key3 = ‘b’,使用 Intersection得到一個交集

2.再使用 key_part1 = ‘a’ AND key_part2 = ‘b’ AND key_part3 = ‘c’,得到一個集合

3.再對上面求到的兩個集合求并集。然后進行回表

優化器只有在單獨根據搜索條件從某個二級索引中獲取的記錄數比較少,通過Union索引合并后進行訪問的代價比全表掃描更小時才會使用Union索引合并。

2.3.3 Sort-Union合并

Union的條件太苛刻了,只有等值匹配才能使用到。

SELECT * FROM single_table WHERE key1 < 'a' OR key3 > 'z'

而對于這樣的范圍查詢就無法使用了,而對于上面的sql就可能執行Sort-Union索引合并。

1.按照key1 < 'a’查出所有記錄,并且排好序
2.按照key3 > 'z’查出所有記錄,并且排好序
3.因為兩個集合的主鍵都是排好序的了,因此直接按Union那樣做就行了

為什么沒有Sort-Intersection?
因為Union是在單獨根據搜索條件從某個二級索引中獲取的記錄數比較少的情況下使用的,而這種情況下記錄數少,排序的性能損耗小。而Intersection的情況恰恰相反,它是針對查詢出的記錄數多,如果排序對于性能的損耗就很大了

2.3.4 聯合索引注意事項

聯合索引替代Intersection索引合并

SELECT * FROM single_table WHERE key1 = 'a' AND key3 = 'b';

像這樣的sql語句,需要使用到兩個單獨的索引,倒不如直接做成聯合索引,既可以少一顆b+樹,還不能做集合運算。

ALTER TABLE single_table drop index idx_key1, idx_key3, add index idx_key1_key3(key1, key3);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/391120.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391120.shtml
英文地址,請注明出處:http://en.pswp.cn/news/391120.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

蝙蝠俠遙控器pcb_通過蝙蝠俠從Circle到ML:第二部分

蝙蝠俠遙控器pcbView Graph查看圖 背景 (Background) Wait! Isn’t the above equation different from what we found last time? Yup, very different but still looks exactly the same or maybe a bit better. Just in case you are wondering what I am talking about, p…

camera驅動框架分析(上)

前言 camera驅動框架涉及到的知識點比較多&#xff0c;特別是camera本身的接口就有很多&#xff0c;有些是直接連接到soc的camif口上的&#xff0c;有些是通過usb接口導出的&#xff0c;如usb camera。我這里主要討論前者&#xff0c;也就是與soc直連的。我認為凡是涉及到usb的…

工程項目管理需要注意哪些問題

在社會科學技術發展和市場經濟繁榮昌盛的今天&#xff0c;為更好的滿足社會人性化的需求&#xff0c;建設施工企業在建筑施工、布局以及內部運行都給予了落實。而工程項目是建筑施工企業面向建筑市場的窗口&#xff0c;是企業建筑活動的前沿陣地&#xff0c;管理需更嚴謹。 雖說…

leetcode 872. 葉子相似的樹(dfs)

請考慮一棵二叉樹上所有的葉子&#xff0c;這些葉子的值按從左到右的順序排列形成一個 葉值序列 。 舉個例子&#xff0c;如上圖所示&#xff0c;給定一棵葉值序列為 (6, 7, 4, 9, 8) 的樹。 如果有兩棵二叉樹的葉值序列是相同&#xff0c;那么我們就認為它們是 葉相似 的。 …

探索感染了COVID-19的動物的數據

數據 (The data) With the number of cases steadily rising day by day, COVID-19 has been pretty much in the headlines of every newspaper known to man. Despite the massive amount of attention, a topic that has remained mostly untouched (some exceptions being …

Facebook哭暈在廁所,調查顯示用VR體驗社交的用戶僅為19%

美國娛樂軟件協會ESA調查顯示&#xff0c;有74%的用戶使用VR玩游戲&#xff0c;而僅有19%的用戶會用VR進行社交。 當我們說到VR社交&#xff0c;必然離不開Facebook。在剛剛結束的F8大會上&#xff0c;小扎展示了VR社交平臺Facebook Spaces測試版&#xff0c;巧的是此前也有好…

網頁自動刷新

eg1&#xff1a;<meta http-equiv”refresh” content”4” /> 間隔4秒網頁自動刷新 eg2&#xff1a;<meta http-equiv”refresh” content”8;http://www.baidu.com” /> 等待8秒自動跳轉到百度頁面轉載于:https://www.cnblogs.com/zwtqf/p/7667774.html

解決Javascript疲勞的方法-以及其他所有疲勞

Learn your fundamentals, and never worry again. 了解您的基礎知識&#xff0c;再也不用擔心。 新工具讓我擔心 (New Tools Worry Me) When JavaScripts shiny tool of the day comes out, I sometimes overreact. 當JavaScript一天一度的閃亮工具問世時&#xff0c;我有時R…

Java 8 的List<V> 轉成 Map<K, V>

問題&#xff1a; Java 8 的List 轉成 Map<K, V> 我想要使用Java 8的streams和lambdas轉換一個 List 對象為 Map 下面是我在Java 7里面的寫法 private Map<String, Choice> nameMap(List<Choice> choices) {final Map<String, Choice> hashMap new…

已知兩點坐標拾取怎么操作_已知的操作員學習-第4部分

已知兩點坐標拾取怎么操作有關深層學習的FAU講義 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU’s YouTube Lecture “Deep Learning”. This is a full transcript of the lecture video & matching slides. We hope, you enjoy this as mu…

北京供銷大數據集團發布SinoBBD Cloud 一體化推動產業云發展

9月5日&#xff0c;第五屆全球云計算大會在上海世博展覽館盛大開幕&#xff0c;國內外頂尖企業匯聚一堂&#xff0c;新一代云計算技術產品紛紛亮相。作為國內領先的互聯網基礎服務提供商&#xff0c;北京供銷大數據集團(以下簡稱“SinoBBD”)受邀參加此次大會&#xff0c;并正式…

windows下有趣的小玩意

1.顯示文件和隱藏文件。在當前目錄下shift右鍵 選擇cmd命令 運行顯示文件: attrib -s -h 文件名 隱藏文件: attrib -s h 文件名 2.查看電腦支持的最大內存 在cmd下運行wmic memphysical get maxcapacity所得結果單位mb 所得/1024/1024 得到單位G 3.windowsR 輸入…

rxjs angular_Angular RxJS深度

rxjs angularIn this tutorial, well learn to use the RxJS 6 library with Angular 6 or Angular 7. Well learn about:在本教程中&#xff0c;我們將學習將RxJS 6庫與Angular 6或Angular 7結合使用。我們將了解&#xff1a; How to import the Observable class and the ot…

HashMap, LinkedHashMap 和 TreeMap的區別

HashMap, LinkedHashMap 和 TreeMap的區別 Java里面的HashMap, LinkedHashMap 和 TreeMap 有什么區別?我看不出以下3個key和value有什么不同的。Hashtables里面又是怎么樣的呢&#xff1f; Map m1 new HashMap(); m1.put("map", "HashMap"); m1.put(&q…

“陪護機器人”研報:距離真正“陪護”還差那么一點

一款有“缺陷”的機器人&#xff0c;怎能做到真正的“陪護”&#xff1f; 近日&#xff0c;鼎盛智能發布了一款名為Ibotn的&#xff08;愛蹦&#xff09;幼兒陪伴機器人&#xff0c;核心看點就是通過人臉識別、場景識別等計算機視覺技術來實現機器人對兒童的陪護。不過&#xf…

neo-6m uno_Uno-統治所有人的平臺

neo-6m unoFirst, we should start off with what Uno is and why you should care. 首先&#xff0c;我們應該從Uno是什么以及為什么要關心開始。 As stated on their website, Uno is "The only platform for building native mobile, desktop and WebAssembly apps wi…

【轉】消息隊列應用場景

一、消息隊列概述 消息隊列中間件是分布式系統中重要的組件&#xff0c;主要解決應用耦合&#xff0c;異步消息&#xff0c;流量削鋒等問題。實現高性能&#xff0c;高可用&#xff0c;可伸縮和最終一致性架構。是大型分布式系統不可缺少的中間件。 目前在生產環境&#xff0c;…

JDK和JRE區別是什么

問題&#xff1a;JDK和JRE區別是什么 他們的角色分別是什么&#xff1f;我們應該什么時候使用他們&#xff1f; 回答一 JRE是Java Runtime Environment&#xff08;Java運行時環境&#xff09;。它是一個包&#xff0c;集合了運行一個編譯好的Java程序的一切必須的東西&…

樹莓派新手入門教程

http://www.ruanyifeng.com/blog/2017/06/raspberry-pi-tutorial.html

lime 模型_使用LIME的糖尿病預測模型解釋— OneZeroBlog

lime 模型Article outline文章大綱 Introduction 介紹 Data Background 資料背景 Aim of the article 本文的目的 Exploratory analysis 探索性分析 Training a Random Forest Model 訓練隨機森林模型 Global Importance 全球重要性 Local Importance 當地重要性 介紹 (Introd…