1.mysql的索引原理和數(shù)據(jù)結構
目錄查詢,B+樹結構
2.B+樹和B樹的區(qū)別是什么
二分查找樹->平衡二叉樹->B樹->B+樹
B樹一個節(jié)點上可以存儲多個鍵值和數(shù)據(jù)
B+樹,非子葉節(jié)點上不存儲數(shù)據(jù),存儲多個鍵值;子葉節(jié)點上順序存儲鍵值和數(shù)據(jù)(聚集索引),子葉節(jié)點不存儲數(shù)據(jù),存儲該列對應的主鍵,查到主鍵后回表查詢,再走聚集索引的查詢流程。
3.mysql聚簇索引和非聚簇索引的區(qū)別
主鍵作為索引和非主鍵列作為索引
聚集索引:葉子節(jié)點順序存儲數(shù)據(jù)
非聚集索引:葉子節(jié)點不存儲數(shù)據(jù),存儲該列對應的主鍵,然后根據(jù)主鍵回表查詢。
如果不設置主鍵,MySQL默認會創(chuàng)建主鍵;
4.使用mysql索引都有什么原則
聯(lián)合索引會有最左原則;
覆蓋索引,查詢列剛好是索引,默認會使用該索引
5.不同的存儲引擎是如何進行實際存儲的
Myisam:存儲數(shù)據(jù)信息
Innodb:存儲地址和文件
6.mysql組合索引的結構是什么樣的
7.mysql索引如何進行優(yōu)化
1.expain分析索引的使用情況;
2.索引字段不要太長;
3.多列索引查詢時可使用聯(lián)合索引;
4.盡量避免使用子查詢;
5.用IN來替換OR
select * from person where name = 'jack' or name = 'lucy';
select * from person where name in ('jack' , 'lucy');
6.讀取適當?shù)挠涗汱IMIT M,而不要讀多余的記錄
select * from person where age > 10 limit 10;
7.不要使用NOT等負向查詢條件;
二分查找的特點,左邊查詢不匹配會到右邊查詢,若使用不等于,則需要全表查詢;
8.盡量不用select *
SELECT *增加很多不必要的消耗(cpu、io、內存、網(wǎng)絡帶寬);
9.區(qū)分in和exists
select * from 表A
where id in (select id from 表B)
select * from 表A
where exists(select * from 表B where 表B.id=表A.id)
如果是exists,那么以__外層表為驅動表,先被訪問__;
如果是IN,那么__先執(zhí)行子查詢__;
所以IN適合于外表大而內表小的情況;
EXISTS適合于外表小而內表大的情況。
10.優(yōu)化Group By語句
如果對group by語句的結果沒有排序要求,要在語句后面加 order by null(group 默認會去排序);
11.索引優(yōu)化:
性能優(yōu)化,left join 是由左邊決定的,左邊一定都有,所以右邊是我們的關鍵點,建立索引要建在右邊。當然如果索引是在左邊的,我們可以考慮使用右連接;
Tips:Join左連接在右邊建立索引;組合索引則盡量將數(shù)據(jù)量大的放在左邊,在左邊建立索引
12.避免索引失效
1、如果索引了多列,要遵守最左前綴法則,指的是查詢從索引的最左前列開始并且不跳過索引中的列。Mysql查詢優(yōu)化器會對查詢的字段進行改進,判斷查詢的字段以哪種形式組合能使得查詢更快,所有比如創(chuàng)建的是(a,b)索引,查詢的是(b,a),查詢優(yōu)化器會修改成(a,b)后使用索引查詢
2、不在索引列上做任何操作,(計算、函數(shù)、(自動or手動)類型轉換),會導致索引失效而轉向全表掃描。)
3、存儲引擎不能使用索引中范圍條件右邊的列。
如這樣的sql: select * from user where username='123' and age>20 and phone='1390012345',其中username, age, phone都有索引,只有username和age會生效,phone的索引沒有用到。
4、盡量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致));
如select age from user減少select *;
5、mysql在使用不等于(!= 或者 <>)的時候無法使用索引會導致全表掃描;
6、is null, is not null 也無法使用索引,在實際中盡量不要使用null;
7、like 以通配符開頭(‘%abc..’)mysql索引失效會變成全表掃描的操作;
所以最好用右邊like 'abc%'
8、字符串不加單引號索引失效;
9、少用or,用它來連接時會索引失效;
10、盡量避免子查詢,而用join;
一、為什么用自增列作為主鍵
1、如果我們定義了主鍵(PRIMARY KEY),那么InnoDB會選擇主鍵作為聚集索引。
如果沒有顯式定義主鍵,則InnoDB會選擇__第一個不包含有NULL值的唯一索引作為主鍵索引__。
如果也沒有這樣的唯一索引,則InnoDB會__選擇內置6字節(jié)長的ROWID作為隱含的聚集索引__(ROWID隨著__行記錄的寫入而主鍵遞增__,這個ROWID不像ORACLE的ROWID那樣可引用,是隱含的)。
2、數(shù)據(jù)記錄本身被存于主索引(一顆B+Tree)的葉子節(jié)點上,這就要求同一個葉子節(jié)點內(大小為一個內存頁或磁盤頁)的各條數(shù)據(jù)記錄按主鍵順序存放;
因此每當有一條新的記錄插入時,MySQL會根據(jù)其主鍵將其插入適當?shù)墓?jié)點和位置,如果頁面達到裝載因子(InnoDB默認為15/16),則開辟一個新的頁(節(jié)點)
3、如果表使用自增主鍵,那么每次插入新的記錄,記錄就會順序添加到當前索引節(jié)點的后續(xù)位置,當一頁寫滿,就會自動開辟一個新的頁
4、如果使用非自增主鍵(如果身份證號或學號等),由于每次插入主鍵的值近似于隨機,因此每次新紀錄都要被插到現(xiàn)有索引頁得中間某個位置;
此時MySQL不得不為了將新記錄插到合適位置而移動數(shù)據(jù),甚至目標頁面可能已經(jīng)被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增加了很多開銷
同時頻繁的移動、分頁操作造成了大量的碎片,得到了不夠緊湊的索引結構,后續(xù)不得不通過OPTIMIZE TABLE來重建表并優(yōu)化填充頁面
二、為什么使用數(shù)據(jù)索引能提高效率
MySql默認是B+樹結構,原因是默認有主鍵索引。
使用索引查詢的時候走索引的查詢流程,同時索引會將子葉節(jié)點頁中的數(shù)據(jù)按序排序;
不使用索引查詢的時候就會遍歷整張表;
https://www.cnblogs.com/xiaoshahai/p/12028737.html
索引可以將無序內容轉換為有序的一個集合(相對),就如同新華字典,如果沒有目錄,那么查詢一個漢字就需要很長時間了;
如果沒有索引我們查詢數(shù)據(jù)是需要遍歷雙向鏈表來定位對應的page,現(xiàn)在通過索引創(chuàng)建的“目錄”就可以很快定位對應頁上了;
數(shù)據(jù)索引的存儲是有序的;
在有序的情況下,通過索引查詢一個數(shù)據(jù)是無需遍歷索引記錄的
極端情況下,數(shù)據(jù)索引的查詢效率為二分法查詢效率,趨近于 log2(N)
什么是哈希索引
哈希索引就是采用一定的哈希算法,把鍵值換算成新的哈希值,檢索
時不需要類似B+樹那樣從根節(jié)點到葉子節(jié)點逐級查找,只需一次哈希
算法即可,是無序的,如下圖所示:

image.png
哈希索引的優(yōu)勢:
等值查詢,哈希索引具有絕對優(yōu)勢(前提是:沒有大量重復鍵值,如
果大量重復鍵值時,哈希索引的效率很低,因為存在所謂的哈希碰撞問題。)
哈希索引不適用的場景:
不支持范圍查詢
不支持索引完成排序
不支持聯(lián)合索引的最左前綴匹配規(guī)則
為什么說B+比B樹更適合實際應用中操作系統(tǒng)的文件索引和數(shù)據(jù)庫索引?
1、B+的磁盤讀寫代價更低。
B+的內部結點并沒有指向關鍵字具體信息的指針,因此其內部結點相
對B樹更小。
如果把所有同一內部結點的關鍵字存放在同一盤塊中,那么盤塊所能
容納的關鍵字數(shù)量也越多。一次性讀入內存中的需要查找的關鍵字也
就越多。相對來說IO讀寫次數(shù)也就降低了。
2、B+-tree的查詢效率更加穩(wěn)定。
由于非終結點并不是最終指向文件內容的結點,而只是葉子結點中關
鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點
的路。所有關鍵字查詢的路徑長度相同,導致每一個數(shù)據(jù)的查詢效率相當。
MySQL聯(lián)合索引
1、聯(lián)合索引是兩個或更多個列上的索引。
對于聯(lián)合索引:Mysql從左到右的使用索引中的字段,一個查詢可以只使用索引中的一部份,但只能是最左側部分。
例如索引是key index (a,b,c). 可以支持a 、 a,b 、 a,b,c 3種組合進行查找,但不支持 b,c進行查找 .當最左側字段是常量引用時,索引就十分有效。
2、利用索引中的附加列,您可以縮小搜索的范圍,但使用一個具有兩列的索引不同于使用兩個單獨的索引。
復合索引的結構與電話簿類似,人名由姓和名構成,電話簿首先按姓氏對進行排序,然后按名字對有相同姓氏的人進行排序。
如果您知道姓,電話簿將非常有用;如果您知道姓和名,電話簿則更為有用,但如果您只知道名不知道姓,電話簿將沒有用處。

image.png
聯(lián)合索引和多個單列索引的區(qū)別
因為MySql優(yōu)化器原因,多個單列索引查詢時查詢并不會按照索引的前后順序去查詢,可能會導致查詢效率變低。
聯(lián)合索引遵循最左原則,可以讓SQL優(yōu)先查詢最最便的索引,之后查詢后面的,不會被SQL優(yōu)化,會按照順序搜索;