mysql 左连接 怎么走索引_数据库索引、左连接、右连接、等值连接
在MySQL中,主要有四種類型的索引,分別為:B-Tree索引,Hash索引,Fulltext索引(MyISAM 表)和R-Tree索引,本文講的是B-Tree索引。
一、Mysql索引主要有兩種結構:B+Tree索引和Hash索引
(a) Innodb存儲引擎 默認是 B+Tree索引
(b) MyISAM 存儲引擎 默認是Fulltext索引;
(c)Memory 存儲引擎 默認 Hash索引;
Hash索引
mysql中,只有Memory(Memory表只存在內存中,斷電會消失,適用于臨時表)存儲引擎顯示支持Hash索引,是Memory表的默認索引類型,盡管Memory表也可以使用B+Tree索引。Hash索引把數據以hash形式組織起來,因此當查找某一條記錄的時候,速度非???。但是因為hash結構,每個鍵只對應一個值,而且是散列的方式分布。所以它并不支持范圍查找和排序等功能。
B+Tree索引
B+Tree是mysql使用最頻繁的一個索引數據結構,是Innodb和Myisam存儲引擎模式的索引類型。相對Hash索引,B+Tree在查找單條記錄的速度比不上Hash索引,但是因為更適合排序等操作,所以它更受歡迎。畢竟不可能只對數據庫進行單條記錄的操作。
帶順序訪問指針的B+Tree
B+Tree所有索引數據都在葉子節點上,并且增加了順序訪問指針,每個葉子節點都有指向相鄰葉子節點的指針。
這樣做是為了提高區間效率,例如查詢key為從18到49的所有數據記錄,當找到18后,只要順著節點和指針順序遍歷就可以以此向訪問到所有數據節點,極大提高了區間查詢效率。
大大減少磁盤I/O讀取
數據庫系統的設計者巧妙利用了磁盤預讀原理,將一個節點的大小設為等于一個頁,這樣每個節點需要一次I/O就可以完全載入。
什么是索引
索引(Index)是幫助數據庫高效獲取數據的數據結構。索引是在基于數據庫表創建的,它包含一個表中某些列的值以及記錄對應的地址,并且把這些值存儲在一個數據結構中。最常見的就是使用哈希表、B+樹作為索引。
一般的應用系統,讀寫比例在10:1左右,而且插入操作和一般的更新操作很少出現性能問題,在生產環境中,我們遇到最多的,也是最容易出問題的,還是一些復雜的查詢操作,因此對查詢語句的優化顯然是重中之重。說起加速查詢,就不得不提到索引了。
為什么要使用索引
我們知道,數據庫查詢是數據庫最主要的功能之一。而查詢速度當然是越快越好。而當數據量越來越大的時候,查詢花費的時間會隨之增長。而索引,可以加速數據的查詢。因為索引是有序排列的。
舉個例子來說,假設我們有一個數據庫表Employee,這個表分別有三個字段:name,age,address。假設表中有1000條記錄。
假如沒有使用索引,當我們查詢名為“Jesus”的雇員的時候,即調用:
select name,age,address from Employee where name = 'Jesus';
此時數據庫不得不在Employee表中對這1000條記錄一條一條的進行判斷name字段是否為“Jesus”。這也就是所謂的全表掃描。
而當我們在Employee表上的name字段上創建索引時,當我們查詢名為“Jesus”的雇員時,會通過索引查找去查詢名為“Jesus”的雇員,因為該索引已經按照字母順序排列,因此要查找名為“Jesus”的記錄時會快很多,因為名字首字母為“J”的雇員都是排列在一起的。通過該索引,能獲取到表中對應的記錄。
二叉查找樹
二叉查找樹也稱為有序二叉查找樹,滿足二叉查找樹的一般性質,是指一棵空樹具有如下性質:
1、任意節點左子樹不為空,則左子樹的值均小于根節點的值;
2、任意節點右子樹不為空,則右子樹的值均大于于根節點的值;
3、任意節點的左右子樹也分別是二叉查找樹;
4、沒有鍵值相等的節點;
平衡二叉樹
樹形結構是計算機系統里最重要的數據結構。
我們知道,二叉樹的查找的時間復雜度是O(log2N),其查找效率與深度有關,而普通的二叉樹可能由于內部節點排列問題退化成鏈表,這樣查找效率就會很低。因此平衡二叉樹是更好的選擇,因為它保持平衡,即通過旋轉調整結構保持最小的深度。其查找的時間復雜度也是O(log2N)。
但實際上,數據庫中索引的結構也并非AVL樹或更優秀的紅黑樹,盡管它的查詢的時間復雜度很低。
為什么平衡二叉樹也不適合作為索引
之前說了平衡樹的查找時間復雜度是O(log2N),已經很不錯了,但還是不適合作為索引結構。那么肯定是有一種更適合作為索引的數據結構。那么這個更適合作為索引的數據結構,難道是查找的時間復雜度更低嗎?并不是。這種作為索引的數據結構的查找的時間復雜度也近似O(log2N)。
那為什么平衡二叉樹不適合作為索引呢?
索引是存在于索引文件中,是存在于磁盤中的。因為索引通常是很大的,因此無法一次將全部索引加載到內存當中,因此每次只能從磁盤中讀取一個磁盤頁的數據到內存中。而這個磁盤的讀取的速度較內存中的讀取速度而言是差了好幾個級別。
注意,我們說的平衡二叉樹結構,指的是邏輯結構上的平衡二叉樹,其物理實現是數組。然后由于在邏輯結構上相近的節點在物理結構上可能會差很遠。因此,每次讀取的磁盤頁的數據中有許多是用不上的。因此,查找過程中要進行許多次的磁盤讀取操作。
而適合作為索引的結構應該是盡可能少的執行磁盤IO操作,因為執行磁盤IO操作非常的耗時。因此,平衡二叉樹并不適合作為索引結構。
B樹的性質
1、定義任意非葉子結點最多只有M個兒子,且M>2;
2、根結點的兒子數為[2, M];
3、除根結點以外的非葉子結點的兒子數為[M/2, M];
4、每個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字)
5、非葉子結點的關鍵字個數=指向兒子的指針個數-1;
6、非葉子結點的關鍵字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
7、非葉子結點的指針:P[1], P[2], …, P[M];其中P[1]指向關鍵字小于K[1]的子樹,P[M]指向關鍵字大于K[M-1]的子樹,其它P[i]指向關鍵字屬于(K[i-1], K[i])的子樹;
8、所有葉子結點位于同一層;
B+樹
比B樹更適合作為索引的結構是B+樹。MySQL中也是使用B+樹作為索引。它是B樹的變種,因此是基于B樹來改進的。為什么B+樹會比B樹更加優秀呢?
B樹:有序數組+平衡多叉樹;
B+樹:有序數組鏈表+平衡多叉樹;
B+樹的關鍵字全部存放在葉子節點中,非葉子節點用來做索引,而葉子節點中有一個指針指向一下個葉子節點。做這個優化的目的是為了提高區間訪問的性能。而正是這個特性決定了B+樹更適合用來存儲外部數據。
MYSQL為什么采用B樹而不是B+樹
1、?B+樹的磁盤讀寫代價更低:B+樹的內部節點并沒有指向關鍵字具體信息的指針,因此其內部節點相對B樹更小,如果把所有同一內部節點的關鍵字存放在同一盤塊中,那么盤塊所能容納的關鍵字數量也越多,一次性讀入內存的需要查找的關鍵字也就越多,相對IO讀寫次數就降低了。
2、B+樹的查詢效率更加穩定:由于非終結點并不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。
3、由于B+樹的數據都存儲在葉子結點中,分支結點均為索引,方便掃庫,只需要掃一遍葉子結點即可,但是B樹因為其分支結點同樣存儲著數據,我們要找到具體的數據,需要進行一次中序遍歷按序來掃,所以B+樹更加適合在區間查詢的情況,所以通常B+樹用于數據庫索引。
數據庫索引采用B+樹的主要原因是B樹在提高了磁盤IO性能的同時并沒有解決元素遍歷的效率低下的問題。正是為了解決這個問題,B+樹應運而生。
B+樹只要遍歷葉子節點就可以實現整棵樹的遍歷。而且在數據庫中基于范圍的查詢是非常頻繁的,而B樹不支持這樣的操作(或者說效率太低)。
正如上面所說,在數據庫中基于范圍的查詢是非常頻繁的,因此MySQL最終選擇的索引結構是B+樹而不是B樹。
b+樹性質
1.索引字段要盡量的小:通過上面的分析,我們知道IO次數取決于b+數的高度h,假設當前數據表的數據為N,每個磁盤塊的數據項的數量是m,則有h=㏒(m+1)N,當數據量N一定的情況下,m越大,h越小;而m = 磁盤塊的大小 / 數據項的大小,磁盤塊的大小也就是一個數據頁的大小,是固定的,如果數據項占的空間越小,數據項的數量越多,樹的高度越低。這就是為什么每個數據項,即索引字段要盡量的小,比如int占4字節,要比bigint8字節少一半。這也是為什么b+樹要求把真實的數據放到葉子節點而不是內層節點,一旦放到內層節點,磁盤塊的數據項會大幅度下降,導致樹增高。當數據項等于1時將會退化成線性表。
2.索引的最左匹配特性(即從左往右匹配):當b+樹的數據項是復合的數據結構,比如(name,age,sex)的時候,b+數是按照從左到右的順序來建立搜索樹的,比如當(張三,20,F)這樣的數據來檢索的時候,b+樹會優先比較name來確定下一步的所搜方向,如果name相同再依次比較age和sex,最后得到檢索的數據;但當(20,F)這樣的沒有name的數據來的時候,b+樹就不知道下一步該查哪個節點,因為建立搜索樹的時候name就是第一個比較因子,必須要先根據name來搜索才能知道下一步去哪里查詢。比如當(張三,F)這樣的數據來檢索時,b+樹可以用name來指定搜索方向,但下一個字段age的缺失,所以只能把名字等于張三的數據都找到,然后再匹配性別是F的數據了, 這個是非常重要的性質,即索引的最左匹配特性。
這也是經常考察的,比如 我定義了 A,B,C的聯合索引,如果 我只傳遞了 A,B 能走索引嗎?答案是能,因為最左側原理
索引使用注意事項
1,不要濫用索引
①,索引提高查詢速度,卻會降低更新表的速度,因為更新表時,mysql不僅要更新數據,保存數據,還要更新索引,保存索引
②,索引會占用磁盤空間
2,索引不會包含含有NULL值的列
復合索引只要有一列含有NULL值,那么這一列對于此符合索引就是無效的,因此我們在設計數據庫設計時不要讓字段的默認值為NULL。
3,MySQL查詢只是用一個索引
如果where字句中使用了索引的話,那么order by中的列是不會使用索引的
4,like
like '%aaa%'不會使用索引而like "aaa%"可以使用索引
二、選擇索引的數據類型
Mysql支持很多數據類型,選擇合適的數據類型存儲數據對性能有很大的影響。
(1)越小的數據類型通常更好:越小的數據類型通常在磁盤、內存和cpu緩存中都需要更少的空間,處理起來更快。
(2)簡單的數據類型更好:整形數據比起字符,處理開銷更小,因為字符串的比較更復雜。在MySQL中,應用內置的日期和時間數據類型,而不是字符串來存儲時間;以及用整形數據存儲IP地址。
(3)盡量避免NULL:應該制定列為NOT NULL,除非你想存儲NULL。在MySQL中,含有空值的列很難進行查詢優化,因為他們使得索引、索引的統計信息以及比較運算更加復雜。
三、MySQL常見索引有:主鍵索引、唯一索引、普通索引、全文索引、組合索引
1,INDEX(普通索引):ALTER TABLE 'table_name' ADD INDEX index_name('col')
最基本的索引,沒有任何限制
2,UNIQUE(唯一索引):ALTER TABLE 'table_name' ADD UNIQUE('col')
與“普通索引”類似,不同的就是:索引列的值必須唯一,但允許有空值。
3,PRIMARY KEY(主鍵索引):ALTER TABLE 'table_name' ADD PRIMARY KEY('col')
是一種特殊的唯一索引,不允許有空值。
4,FULLTEXT(全文索引):ALTER TABLE 'table_name' ADD FULLTEXT('col')
僅可用于MyISAM和InoDB,針對較大的數據,生成全文索引很耗時耗空間
組合索引:ALTER TABLE 'table_name' ADD INDEX index_name('col1','col2','col3')
為了更多的提高mysql效率可建立組合索引,遵循“最左前綴”原則。創建復合索引應該將最常用(頻率)做限制條件的列放在最左邊,一次遞減。組合索引最左字段用in是可以用到索引的。相當于建立了col1,col1col2,col1col2col3三個索引
聚集索引和輔助索引
數據庫中的B+Tree索引可以分為聚集索引(clustered index)和輔助索引(secondary index)。上面的B+Tree示例圖在數據庫中的實現即為聚集索引,聚集索引的B+Tree中的葉子節點存放的是整張表的行記錄數據。輔助索引與聚集索引的區別在于輔助索引的葉子節點并不包含行記錄的全部數據,而是存儲相應行數據的聚集索引鍵,即主鍵。當通過輔助索引來查詢數據時,InnoDB存儲引擎會遍歷輔助索引找到主鍵,然后再通過主鍵在聚集索引中找到完整的行記錄數據
數據庫適合創建索引的規則如下:
表的主鍵,外鍵應該創建索引;
數據量比較大的表應該創建索引;
經常需要和其他表建立連接,在連接字段應該創建索引;
經常出現在where子句中的字段,應該創建索引。
數據庫不適合創建索引的情況:
比較大的文本字段或者長度較長的字段,不適合創建索引;
頻繁進行數據操作的表,不適合創建過多的索引,因為額外維護索引表需要更多的開銷;
小型表(數據量低于300行)不要建立索引。
參考鏈接:
總結
以上是生活随笔為你收集整理的mysql 左连接 怎么走索引_数据库索引、左连接、右连接、等值连接的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 游戏《坦克世界》电脑配置
- 下一篇: linux select读取节点数据失败