mysql高級教程(一)-----邏輯架構、查詢流程、索引


mysql邏輯架構

和其它數據庫相比,MySQL有點與眾不同,它的架構可以在多種不同場景中應用並發揮良好作用。主要體現在存儲引擎的架構上,插件式的存儲引擎架構將查詢處理和其它的系統任務以及數據的存儲提取相分離。這種架構可以根據業務的需求和實際需要選擇合適的存儲引擎。   

1.連接層 

最上層是一些客戶端和連接服務,包含本地sock通信和大多數基於客戶端/服務端工具實現的類似於tcp/ip的通信。主要完成一些類似於連接處理、授權認證、及相關的安全方案。在該層上引入了線程池的概念,為通過認證安全接入的客戶端提供線程。同樣在該層上可以實現基於SSL的安全鏈接。服務器也會為安全接入的每個客戶端驗證它所具有的操作權限。 

2.服務層 

2.1  Management Serveices & Utilities:

系統管理和控制工具  

2.2  SQL Interface: SQL接口     

接受用戶的SQL命令,並且返回用戶需要查詢的結果。比如select from就是調用SQL Interface

2.3 Parser: 解析器      

SQL命令傳遞到解析器的時候會被解析器驗證和解析。 

2.4 Optimizer: 查詢優化器

SQL語句在查詢之前會使用查詢優化器對查詢進行優化。     

用一個例子就可以理解:

select uid,name from user where  gender= 1;    

優化器來決定先投影還是先過濾。  

2.5 Cache和Buffer: 查詢緩存。     

如果查詢緩存有命中的查詢結果,查詢語句就可以直接去查詢緩存中取數據。     

這個緩存機制是由一系列小緩存組成的。比如表緩存,記錄緩存,key緩存,權限緩存等       

緩存是負責讀,緩沖負責寫。  

3.引擎層  

存儲引擎層,存儲引擎真正的負責了MySQL中數據的存儲和提取,服務器通過API與存儲引擎進行通信。不同的存儲引擎具有的功能不同,這樣我們可以根據自己的實際需要進行選取。最常用的則是MyISAM和InnoDB ,二者對比如下:

4.存儲層 

數據存儲層,主要是將數據存儲在運行於裸設備的文件系統之上,並完成與存儲引擎的交互。

邏輯架構圖如下:

查詢流程

針對以下一條普通的select語句,執行流程是啥樣的呢?

select * from student;

連接器 

第一步,你會先連接到這個數據庫上,這時候接待你的就是連接器。連接器負責跟客戶端建立連 接、獲取權限、維持和管理連接。連接命令一般是這么寫的:

mysql -h$ip -P$port -u$user -p

輸完命令之后,你就需要在交互對話里面輸入密碼。雖然密碼也可以直接跟在 -p 后面寫在命令 行中,但這樣可能會導致你的密碼泄露。如果你連的是生產服務器,強烈建議你不要這么做。

連接命令中的 mysql 是客戶端工具,用來跟服務端建立連接。在完成經典的 TCP 握手后,連接器就要開始認證你的身份,這個時候用的就是你輸入的用戶名和密碼。

  • 如果用戶名或密碼不對,你就會收到一個"Access denied for user"的錯誤,然后客戶端程序 結束執行。
  • 如果用戶名密碼認證通過,連接器會到權限表里面查出你擁有的權限。之后,這個連接里面 的權限判斷邏輯,都將依賴於此時讀到的權限。

這就意味着,一個用戶成功建立連接后,即使你用管理員賬號對這個用戶的權限做了修改,也不 會影響已經存在連接的權限。修改完成后,只有再新建的連接才會使用新的權限設置。 連接完成后,如果你沒有后續的動作,這個連接就處於空閑狀態,你可以在 show processlist 命令中看到它。文本中這個圖是 show processlist 的結果,其中的 Command 列顯示 為“Sleep”的這一行,就表示現在系統里面有一個空閑連接。

客戶端如果太長時間沒動靜,連接器就會自動將它斷開。這個時間是由參數 wait_timeout 控制 的,默認值是 8 小時。

如果在連接被斷開之后,客戶端再次發送請求的話,就會收到一個錯誤提醒: Lost connection to MySQL server during query。這時候如果你要繼續,就需要重連,然后再執行請求了。 

數據庫里面,長連接是指連接成功后,如果客戶端持續有請求,則一直使用同一個連接。短連接 則是指每次執行完很少的幾次查詢就斷開連接,下次查詢再重新建立一個。 

建立連接的過程通常是比較復雜的,所以我建議你在使用中要盡量減少建立連接的動作,也就是 盡量使用長連接。 

但是全部使用長連接后,你可能會發現,有些時候 MySQL 占用內存漲得特別快,這是因為 MySQL 在執行過程中臨時使用的內存是管理在連接對象里面的。這些資源會在連接斷開的時候 才釋放。所以如果長連接累積下來,可能導致內存占用太大,被系統強行殺掉(OOM),從現 象看就是 MySQL 異常重啟了。 

怎么解決這個問題呢?你可以考慮以下兩種方案。

  • 1. 定期斷開長連接。使用一段時間,或者程序里面判斷執行過一個占用內存的大查詢后,斷開 連接,之后要查詢再重連。
  • 2. 如果你用的是 MySQL 5.7 或更新版本,可以在每次執行一個比較大的操作后,通過執行 mysql_reset_connection 來重新初始化連接資源。這個過程不需要重連和重新做權限驗 證,但是會將連接恢復到剛剛創建完時的狀態。 

查詢緩存 

連接建立完成后,你就可以執行 select 語句了。執行邏輯就會來到第二步:查詢緩存。

MySQL 拿到一個查詢請求后,會先到查詢緩存看看,之前是不是執行過這條語句。之前執行過 的語句及其結果可能會以 key-value 對的形式,被直接緩存在內存中。key 是查詢的語句, value 是查詢的結果。如果你的查詢能夠直接在這個緩存中找到 key,那么這個 value 就會被直 接返回給客戶端。

如果語句不在查詢緩存中,就會繼續后面的執行階段。執行完成后,執行結果會被存入查詢緩存 中。你可以看到,如果查詢命中緩存,MySQL 不需要執行后面的復雜操作,就可以直接返回結 果,這個效率會很高。 

但是大多數情況下我會建議你不要使用查詢緩存,為什么呢?因為查詢緩存往往弊大於利。

查詢緩存的失效非常頻繁,只要有對一個表的更新,這個表上所有的查詢緩存都會被清空。因此 很可能你費勁地把結果存起來,還沒使用呢,就被一個更新全清空了。對於更新壓力大的數據庫 來說,查詢緩存的命中率會非常低。除非你的業務就是有一張靜態表,很長時間才會更新一次。 比如,一個系統配置表,那這張表上的查詢才適合使用查詢緩存。 

好在 MySQL 也提供了這種“按需使用”的方式。你可以將參數 query_cache_type 設置成 DEMAND,這樣對於默認的 SQL 語句都不使用查詢緩存。而對於你確定要使用查詢緩存的語句,可以用 SQL_CACHE 顯式指定,像下面這個語句一樣:

mysql> select SQL_CACHE * from T where ID=10

需要注意的是,MySQL 8.0 版本直接將查詢緩存的整塊功能刪掉了,也就是說 8.0 開始徹底沒 有這個功能了。

分析器 

如果沒有命中查詢緩存,就要開始真正執行語句了。首先,MySQL 需要知道你要做什么,因此 需要對 SQL 語句做解析。 

分析器先會做“詞法分析”。你輸入的是由多個字符串和空格組成的一條 SQL 語句,MySQL 需要識別出里面的字符串分別是什么,代表什么。 

MySQL 從你輸入的"select"這個關鍵字識別出來,這是一個查詢語句。它也要把字符串“T”識 別成“表名 T”,把字符串“ID”識別成“列 ID”。 

做完了這些識別以后,就要做“語法分析”。根據詞法分析的結果,語法分析器會根據語法規 則,判斷你輸入的這個 SQL 語句是否滿足 MySQL 語法。 

如果你的語句不對,就會收到“You have an error in your SQL syntax”的錯誤提醒,比如下 面這個語句 select 少打了開頭的字母“s”。 

mysql> elect * from t where ID=1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds t

一般語法錯誤會提示第一個出現錯誤的位置,所以你要關注的是緊接“use near”的內容。

優化器 

經過了分析器,MySQL 就知道你要做什么了。在開始執行之前,還要先經過優化器的處理。 優化器是在表里面有多個索引的時候,決定使用哪個索引;或者在一個語句有多表關聯(join) 的時候,決定各個表的連接順序。比如你執行下面這樣的語句,這個語句是執行兩個表的join: 

mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
  • 既可以先從表 t1 里面取出 c=10 的記錄的 ID 值,再根據 ID 值關聯到表 t2,再判斷 t2 里面 d 的值是否等於 20。
  • 也可以先從表 t2 里面取出 d=20 的記錄的 ID 值,再根據 ID 值關聯到 t1,再判斷 t1 里面 c 的值是否等於 10。

這兩種執行方法的邏輯結果是一樣的,但是執行的效率會有不同,而優化器的作用就是決定選擇 使用哪一個方案。

優化器階段完成后,這個語句的執行方案就確定下來了,然后進入執行器階段。如果你還有一些 疑問,比如優化器是怎么選擇索引的,有沒有可能選擇錯等等,沒關系,我會在后面的文章中單 獨展開說明優化器的內容。

執行器

MySQL 通過分析器知道了你要做什么,通過優化器知道了該怎么做,於是就進入了執行器階 段,開始執行語句。 

開始執行的時候,要先判斷一下你對這個表 T 有沒有執行查詢的權限,如果沒有,就會返回沒 有權限的錯誤,如下所示 (在工程實現上,如果命中查詢緩存,會在查詢緩存放回結果的時候, 做權限驗證。查詢也會在優化器之前調用 precheck 驗證權限)。 

mysql> select * from T where ID=10;
ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'

如果有權限,就打開表繼續執行。打開表的時候,執行器就會根據表的引擎定義,去使用這個引 擎提供的接口。

比如我們這個例子中的表 T 中,ID 字段沒有索引,那么執行器的執行流程是這樣的:

  • 1. 調用 InnoDB 引擎接口取這個表的第一行,判斷 ID 值是不是 10,如果不是則跳過,如果 是則將這行存在結果集中;
  • 2. 調用引擎接口取“下一行”,重復相同的判斷邏輯,直到取到這個表的最后一行。
  • 3. 執行器將上述遍歷過程中所有滿足條件的行組成的記錄集作為結果集返回給客戶端。

至此,這個語句就執行完成了。 

對於有索引的表,執行的邏輯也差不多。第一次調用的是“取滿足條件的第一行”這個接口,之 后循環取“滿足條件的下一行”這個接口,這些接口都是引擎中已經定義好的。 

你會在數據庫的慢查詢日志中看到一個 rows_examined 的字段,表示這個語句執行過程中掃描 了多少行。這個值就是在執行器每次調用引擎獲取數據行的時候累加的。在有些場景下,執行器調用一次,在引擎內部則掃描了多行,因此引擎掃描行數跟 rows_examined 並不是完全相同的。 

索引優化分析 

 sql查詢慢的原因

1、查詢數據過多-----能不能拆,條件過濾盡量少

2、關聯了太多的表,太多join-----join 原理。用  A 表的每一條數據 掃描 B表的所有數據。所以盡量先過濾。

3、 沒有利用到索引----- 索引針對列建索引。但並不可能每一列都建索引索引並非越多越好。當數據更新了,索引會進行調整。也會很消耗性能。且 mysql 並不會把所有索引都用上,只會根據其算法挑一個索引用。所以建的准很重要。(單值

             索引、復合索引)

4、索引失效-----在索引列上使用mysql的內置函數、隱式轉換導致索引失效、對索引列進行運算導致索引失效,我所指的對索引列進行運算包括(+,-,*,/,! 等) 、如果MySQL估計使用索引比全表掃描更慢,則不使用索引。。。

5、服務器調優及各個參數設置(緩沖、線程數等)-----一般DBA做這個事,不然要他干嘛~~~

sql執行順序

對於如下一條sql語句:

 

索引

概念

MySQL官方對索引的定義為:索引(Index)是幫助MySQL高效獲取數據的數據結構。可以得到索引的本質:索引是數據結構。你可以簡單理解為“排好序的快速查找數據結構”。

索引的目的在於提高查詢效率,可以類比字典,如果要查“mysql”這個單詞,我們肯定需要定位到m字母,然后從下往下找到y字母,再找到剩下的sql。如果沒有索引,那么你可能需要a----z,如果我想找到Java開頭的單詞呢?或者Oracle開頭的單詞呢?是不是覺得如果沒有索引,這個事情根本無法完成? 

索引結構

在數據之外,數據庫系統還維護着滿足特定查找算法的數據結構,這些數據結構以某種方式引用(指向)數據,這樣就可以在這些數據結構上實現高級查找算法。這種數據結構,就是索引。

下圖就是一種可能的索引方式示例:

左邊是數據表,一共有兩列七條記錄,最左邊的是數據記錄的物理地址 為了加快Col2的查找,可以維護一個右邊所示的二叉查找樹,每個節點分別包含索引鍵值和一個指向對應數據記錄物理地址的指針,這樣就可以運用二叉查找在一定的復雜度內獲取到相應數據,從而快速的檢索出符合條件的記錄。

二叉樹弊端之一:二叉樹很可能會發生兩邊不平衡的情況。

B-TREE: (B:balance)  會自動根據兩邊的情況自動調節,使兩端無限趨近於平衡狀態。可以使性能最穩定。(myisam使用的方式)   

B-TREE弊端:(插入/修改操作多時,B-TREE會不斷調整平衡,消耗性能)從側面說明了索引不是越多越好。

B+TREE:Innodb 所使用的索引 。

一般來說索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲的磁盤上。

優點與缺點

優點:

  • 類似大學圖書館建書目索引,提高數據檢索的效率,降低數據庫的IO成本。
  • 通過索引列對數據進行排序,降低數據排序的成本,降低了CPU的消耗。

缺點:

  • 實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,所以索引列也是要占用空間的。
  • 雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數據,還要保存一下索引文件每次更新添加了索引列的字段,都會調整因為更新所帶來的鍵值變化后的索引信息。

總結:索引只是提高效率的一個因素,如果你的MySQL有大數據量的表,就需要花時間研究建立最優秀的索引,或優化查詢語句

分類

主鍵索引:設定為主鍵后數據庫會自動建立索引,innodb為聚簇索引(聚簇索引的葉節點就是數據節點,而非聚簇索引的頁節點仍然是索引檢點,並保留一個鏈接指向對應數據塊)

單值索引:即一個索引只包含單個列,一個表可以有多個單列索引

唯一索引:索引列的值必須唯一,但允許有空值

復合索引:即一個索引包含多個列

索引常見模型 

索引的出現是為了提高查詢效率,但是實現索引的方式卻有很多種,所以這里也就引入了索引模 型的概念。可以用於提高讀寫效率的數據結構很多,這里我先給你介紹三種常見、也比較簡單的數據結構,它們分別是哈希表、有序數組和搜索樹。 

我們平常所說的索引,如果沒有特別指明,都是指B樹(多路搜索樹,並不一定是二叉的)結構組織的索引。其中聚集索引,次要索引,覆蓋索引,復合索引,前綴索引,唯一索引默認都是使用B+樹索引,統稱索引。當然,除了B+樹這種類型的索引之外,還有哈稀索引(hash index)等。

哈希表 

哈希表是一種以鍵 - 值(key-value)存儲數據的結構,我們只要輸入待查找的值即 key,就可以找到其對應的值即 Value。哈希的思路很簡單,把值放在數組里,用一個哈希函數把 key 換算成一個確定的位置,然后把 value 放在數組的這個位置。 

不可避免地,多個 key 值經過哈希函數的換算,會出現同一個值的情況。處理這種情況的一種 方法是,拉出一個鏈表。 

假設,你現在維護着一個身份證信息和姓名的表,需要根據身份證號查找對應的名字,這時對應的哈希索引的示意圖如下所示: 

圖中,User2 和 User4 根據身份證號算出來的值都是 N,但沒關系,后面還跟了一個鏈表。假 設,這時候你要查 ID_card_n2 對應的名字是什么,處理步驟就是:首先,將 ID_card_n2 通過 哈希函數算出 N;然后,按順序遍歷,找到 User2。

需要注意的是,圖中四個 ID_card_n 的值並不是遞增的,這樣做的好處是增加新的 User 時速度 會很快,只需要往后追加。但缺點是,因為不是有序的,所以哈希索引做區間查詢的速度是很慢 的。 

你可以設想下,如果你現在要找身份證號在 [ID_card_X, ID_card_Y] 這個區間的所有用戶,就 必須全部掃描一遍了。 

所以,哈希表這種結構適用於只有等值查詢的場景,比如 Memcached 及其他一些 NoSQL 引擎。

有序數組

而有序數組在等值查詢和范圍查詢場景中的性能就都非常優秀。還是上面這個根據身份證號查名 字的例子,如果我們使用有序數組來實現的話,示意圖如下所示:

這里我們假設身份證號沒有重復,這個數組就是按照身份證號遞增的順序保存的。這時候如果你 要查 ID_card_n2 對應的名字,用二分法就可以快速得到,這個時間復雜度是 O(log(N))。

同時很顯然,這個索引結構支持范圍查詢。你要查身份證號在 [ID_card_X, ID_card_Y] 區間的 User,可以先用二分法找到 ID_card_X(如果不存在 ID_card_X,就找到大於 ID_card_X 的第 一個 User),然后向右遍歷,直到查到第一個大於 ID_card_Y 的身份證號,退出循環。 

如果僅僅看查詢效率,有序數組就是最好的數據結構了。但是,在需要更新數據的時候就麻煩 了,你往中間插入一個記錄就必須得挪動后面所有的記錄,成本太高。 

所以,有序數組索引只適用於靜態存儲引擎,比如你要保存的是 2017 年某個城市的所有人口信 息,這類不會再修改的數據。 

二叉查找樹 

二叉搜索樹的特點是:每個節點的左兒子小於父節點,父節點又小於右兒子。這樣如果你要查 ID_card_n2 的話,按照圖中的搜索順序就是按照 UserA -> UserC -> UserF -> User2 這個路 徑得到。這個時間復雜度是 O(log(N))。

當然為了維持 O(log(N)) 的查詢復雜度,你就需要保持這棵樹是平衡二叉樹。為了做這個保 證,更新的時間復雜度也是 O(log(N))。

樹可以有二叉,也可以有多叉。多叉樹就是每個節點有多個兒子,兒子之間的大小保證從左到右 遞增。二叉樹是搜索效率最高的,但是實際上大多數的數據庫存儲卻並不使用二叉樹。其原因 是,索引不止存在內存中,還要寫到磁盤上。

 你可以想象一下一棵 100 萬節點的平衡二叉樹,樹高 20。一次查詢可能需要訪問 20 個數據 塊。在機械硬盤時代,從磁盤隨機讀一個數據塊需要 10 ms 左右的尋址時間。也就是說,對於 一個 100 萬行的表,如果使用二叉樹來存儲,單獨訪問一個行可能需要 20 個 10 ms 的時間, 這個查詢可真夠慢的。

為了讓一個查詢盡量少地讀磁盤,就必須讓查詢過程訪問盡量少的數據塊。那么,我們就不應該 使用二叉樹,而是要使用“N 叉”樹。這里,“N 叉”樹中的“N”取決於數據塊的大小。

以 InnoDB 的一個整數字段索引為例,這個 N 差不多是 1200。這棵樹高是 4 的時候,就可以 存 1200 的 3 次方個值,這已經 17 億了。考慮到樹根的數據塊總是在內存中的,一個 10 億行 的表上一個整數字段的索引,查找一個值最多只需要訪問 3 次磁盤。其實,樹的第二層也有很 大概率在內存中,那么訪問磁盤的平均次數就更少了。

B+Tree(InnoDB 的索引模型)

【初始化介紹】 一顆b樹,淺藍色的塊我們稱之為一個磁盤塊,可以看到每個磁盤塊包含幾個數據項(深藍色所示)和指針(黃色所示),如磁盤塊1包含數據項17和35,包含指針P1、P2、P3,P1表示小於17的磁盤塊,P2表示在17和35之間的磁盤塊,P3表示大於35的磁盤塊。真實的數據存在於葉子節點即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非葉子節點不存儲真實的數據,只存儲指引搜索方向的數據項,如17、35並不真實存在於數據表中。 

【查找過程】如果要查找數據項29,那么首先會把磁盤塊1由磁盤加載到內存,此時發生一次IO,在內存中用二分查找確定29在17和35之間,鎖定磁盤塊1的P2指針,內存時間因為非常短(相比磁盤的IO)可以忽略不計,通過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內存,發生第二次IO,29在26和30之間,鎖定磁盤塊3的P2指針,通過指針加載磁盤塊8到內存,發生第三次IO,同時內存中做二分查找找到29,結束查詢,總計三次IO。 真實的情況是,3層的b+樹可以表示上百萬的數據,如果上百萬的數據查找只需要三次IO,性能提高將是巨大的,如果沒有索引,每個數據項都要發生一次IO,那么總共需要百萬次的IO,顯然成本非常非常高。 

假設,我們有一個主鍵列為 ID 的表,表中有字段 k,並且在 k 上有索引。

這個表的建表語句是:

mysql> create table T(
id int primary key,
k int not null,
name varchar(16),
index (k))engine=InnoDB;

表中 R1~R5 的 (ID,k) 值分別為 (100,1)、(200,2)、(300,3)、(500,5) 和 (600,6),兩棵樹的示 例示意圖如下。

從圖中不難看出,根據葉子節點的內容,索引類型分為主鍵索引和非主鍵索引。主鍵索引的葉子節點存的是整行數據。在 InnoDB 里,主鍵索引也被稱為聚簇索引(clustered index)。非主鍵索引的葉子節點內容是主鍵的值。在 InnoDB 里,非主鍵索引也被稱為二級索引.

根據上面的索引結構說明,我們來討論一個問題:基於主鍵索引和普通索引的查詢有什么區別?

  • 如果語句是 select * from T where ID=500,即主鍵查詢方式,則只需要搜索 ID 這棵 B+ 樹;
  • 如果語句是 select * from T where k=5,即普通索引查詢方式,則需要先搜索 k 索引樹, 得到 ID 的值為 500,再到 ID 索引樹搜索一次。這個過程稱為回表。

也就是說,基於非主鍵索引的查詢需要多掃描一棵索引樹。因此,我們在應用中應該盡量使用主鍵查詢。

B+Tree與BTree區別:

結論在內存有限的情況下,B+TREE 永遠比 B-TREE好。無限內存則后者方便  

1)B-樹的關鍵字和記錄是放在一起的,葉子節點可以看作外部節點,不包含任何信息;B+樹葉子節點中只有關鍵字和指向下一個節點的索引,記錄只放在葉子節點中。(一次查詢可能進行兩次i/o操作) 

2)在B-樹中,越靠近根節點的記錄查找時間越快,只要找到關鍵字即可確定記錄的存在;而B+樹中每個記錄的查找時間基本是一樣的,都需要從根節點走到葉子節點,而且在葉子節點中還要再比較關鍵字。從這個角度看B-樹的性能好像要比B+樹好,而在實際應用中卻是B+樹的性能要好些。因為B+樹的非葉子節點不存放實際的數據,這樣每個節點可容納的元素個數比B-樹多,樹高比B-樹小,這樣帶來的好處是減少磁盤訪問次數。盡管B+樹找到一個記錄所需的比較次數要比B-樹多,但是一次磁盤訪問的時間相當於成百上千次內存比較的時間,因此實際中B+樹的性能可能還會好些,而且B+樹的葉子節點使用指針連接在一起,方便順序遍歷(例如查看一個目錄下的所有文件,一個表中的所有記錄等),這也是很多數據庫和文件系統使用B+樹的緣故。  

思考:為什么說B+樹比B-樹更適合實際應用中操作系統的文件索引和數據庫索引? 

1) B+樹的磁盤讀寫代價更低   

B+樹的內部結點並沒有指向關鍵字具體信息的指針。因此其內部結點相對B 樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那么盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找的關鍵字也就越多。相對來說IO讀寫次數也就降低了。 

2) B+樹的查詢效率更加穩定   

由於非終結點並不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。 

聚簇索引與非聚簇索引 

  • 聚簇索引:將數據存儲與索引放到了一塊,找到索引也就找到了數據
  • 非聚簇索引:將數據存儲於索引分開結構,索引結構的葉子節點指向了數據的對應行,myisam通過key_buffer把索引先緩存到內存中,當需要訪問數據時(通過索引訪問數據),在內存中直接搜索索引,然后通過索引找到磁盤相應數據,這也就是為什么索引不在key buffer命中時,速度慢的原因

哪些情況需要創建索引   

1、主鍵自動建立唯一索引

2、頻繁作為查詢條件的字段應該創建索引(where 后面的語句)

3、查詢中與其它表關聯的字段,外鍵關系建立索引 

4、單鍵/組合索引的選擇問題,who?(在高並發下傾向創建組合索引) 

5、查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度

6、查詢中統計或者分組字段

哪些情況不要建索引

1、表記錄太少

2、經常增刪改的表-----Why:提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。因為更新表時,MySQL不僅要保存數據,還要保存一下索引文件

3、Where條件里用不到的字段不創建索引

4、數據重復且分布平均的表字段,因此應該只為最經常查詢和最經常排序的數據列建立索引。-----注意,如果某個數據列包含許多重復的內容,為它建立索引就沒有太大的實際效果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM