mysql b-a全局索引_MySQL中B+树索引的使用
1)???????? 不同應用中B+樹索引的使用
對于OLTP應用,由于數據量獲取可能是其中一小部分,建立B+樹索引是有異議時的
對OLAP應用,情況比較復雜,因為索引的添加應該是宏觀的而不是微觀的。
2)???????? 聯合索引
對表上多個列進行索引。聯合索引的創建方法與多個索引創建的方法一樣。不同之處在于有多個索引頁
CREATE TABLEt(
aINT,
bINT,PRIMARY KEY(a),KEYidx_a_b(a,b)
)ENGINE=INNODB
從本質上來說,聯合索引也是一棵B+樹,不同的聯合索引的鍵值的數量不是1,而是大于等于2。
討論一下由2個整數列組成的聯合索引,分別為a,b
可以看到鍵值是順序的,通過葉子節點可以邏輯上順序地讀出所有的數據,即(1,1)(1,2)(2,1)(2,4)(3,1)(3,2)。數據按(a,b)順序存放
因此對于查詢SELECT * FROM TABLE WHERE a = 1 and b=2,顯然是可以使用(a,b)聯合索引的。對于單列a查詢SELECT * FROM TABLE WHERE a = 1,也是可以用到這個(a,b)索引,但是對于b列SELECT * FROM TABLE WHERE b = 2則不可以使用B+樹索引。可以發現葉子節點上b列的值為1 2 1 4 1 2 不是順序的。因此對于b列的查詢是使用不到(a,b)的索引
聯合索引的第二個好處是已經對第二個鍵值進行排序處理。例如在很多情況下,需要對某個用戶的購物情況進行查詢,并且按照時間排序最后取出最近三次的購物記錄,使用聯合索引可以避免多一次的排序操作。因為索引本身在葉子節點已經排序了。
CREATE TABLEbuy_log(
useridINT UNSIGNED NOT NULL,
buy_date DATE
)ENGINE=INNODB;INSERT INTO buy_log VALUES(1,'2009-01-01');INSERT INTO buy_log VALUES(2,'2009-01-01');INSERT INTO buy_log VALUES(3,'2009-01-01');INSERT INTO buy_log VALUES(1,'2009-02-01');INSERT INTO buy_log VALUES(3,'2009-02-01');INSERT INTO buy_log VALUES(1,'2009-03-01');INSERT INTO buy_log VALUES(1,'2009-04-01');ALTER TABLE buy_log ADD KEY(userid);ALTER TABLE buy_log ADD KEY(userid,buy_date);
建立了兩個索引做比較。都包含userid。
SELECT * FROM buy_log WHERE userid=2;
查看優化器的選擇
可以看到兩個索引都可以使用。但優化器最終使用了userid,因為該索引的葉子節點包含單個鍵值。所以理論上一個頁能存放的記錄應該更多
假定要取出userid=1的最近3次記錄
EXPLAIN SELECT * FROM buy_log WHERE userid=1 ORDER BY buy_date DESC LIMIT 3;
這次優化器使用了(userid,buy_date)的聯合索引userid_2 因為在這個聯合索引中buy_date已經排序了。根據該聯合索引取出數據,無須在對buy_date做一次額外的排序操作。若強制使用userid索引
EXPLAIN SELECT * FROM buy_log FORCE INDEX(userid) WHERE userid=1 ORDER BY buy_date DESC LIMIT 3;
可以看到Using filesort,即需要額外的一次排序操作才能完成查詢。顯然是對buy_date排序。因為索引userid中的buy_date是未排序的
聯合索引(a,b)其實是根據列a,b進行排序的,故此下面語句可以直接使用聯合索引得到結果
EXPLAIN SELECT * FROM TABLE WHERE a=1 ORDER BY b;
對于聯合索引(a,b,c) 也可以直接通過聯合索引得到結果
EXPLAIN SELECT * FROM TABLE WHERE a=1 and b = 1 ORDER BYc;
EXPLAINSELECT * FROM TABLE WHERE a=1 ORDER BY b;
但是對于下面語句,就不能得到結果了,需要執行一次filesort排序操作因為(a,c)并未排序
EXPLAIN SELECT * FROM TABLE WHERE a=1 ORDER BY c;
3)???????? 覆蓋索引
InnoDB存儲引擎支持覆蓋索引,即從輔助索引中就可以查詢到記錄,而不需要查詢聚集索引中的記錄。使用覆蓋索引的一個好處是輔助索引不包含整行記錄的所有信息,故其大小遠小于聚集索引。因此可以減少大量的IO操作
對于InnoDB存儲引擎的輔助索引,由于其包含了主鍵信息,因此其葉子節點存放的數據為(parimary key1,parimary key2,...key1,key2,...)例如,下面語句都可僅使用一次輔助聯合索引來完成查詢
SELECT key2 FROM table WHERE key1=xxx;SELECT primary key2,key2 FROM table key1=xxx;SELECT primary key1,key2 FROM table key1=xxx;SELECT primary key1,primary key2,key2 FROM table key1=xxx;
覆蓋索引的另一個好處是對某些統計問題而言,如上的buy_log,要進行如下查詢
SELECT COUNT(*) FROM buy_log;
InnoDB存儲引擎并不會選擇通過查詢聚集索引來進行統計。由于buy_log還有輔助索引,而輔助索引遠小于聚集索引。選擇輔助索引可以減少IO操作。
如圖顯示。possible_keys是NULL,但是實際執行優化器卻選擇了userid,而列Extra的Using index就是代表優化器選擇了覆蓋索引的操作
此外,在通常情況下,(a,b)的聯合索引,一半是不可以選擇列b中所謂的查詢條件,但是如果是統計操作,并且是覆蓋索引的。則優化器會進行選擇
EXPLAIN SELECT COUNT(*) FROM buy_log WHERE buy_date>='2011-01-01' AND buy_date
表buy_log有(userid,buy_date)聯合索引,這里只根據b進行了條件查詢,一般情況下,是不能進行該聯合索引的。但這條SQL語句查詢是統計操作。并且可以利用覆蓋索引的信息。因此優化器是會選擇聯合索引的。
總結
以上是生活随笔為你收集整理的mysql b-a全局索引_MySQL中B+树索引的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 日利率0.05%月息多少
- 下一篇: php mysql 数据字典_php如何