三茅特、創(chuàng)建高性能的索引

馬上就要到國(guó)慶節(jié)了棋枕,好是期待呀。最近一直忙成狗重斑,急需一個(gè)長(zhǎng)假調(diào)整一下自己的心境和狀態(tài)

期待.jpg

今天我們要說(shuō)的是索引相關(guān)的知識(shí),這也是數(shù)據(jù)庫(kù)的一個(gè)重點(diǎn)章節(jié)祖很。趕緊準(zhǔn)備好你的筆,跟著我一起勾畫(huà)重點(diǎn)吧假颇,聽(tīng)說(shuō)這里要考哦~~~

索引的作用

  1. 可以快速根據(jù)索引查找指定的記錄
  2. 可以根據(jù)索引對(duì)記錄進(jìn)行排序,可以用來(lái)order by 和group by
  3. 可以將隨機(jī)IO轉(zhuǎn)變?yōu)轫樞騃O,索引是有順序的骨稿,先根據(jù)索引順序查詢,然后根據(jù)查找到的關(guān)鍵值定位記錄
三星系統(tǒng)
  1. 索引將相關(guān)的記錄放在一起坦冠,獲得一星
  2. 如果索引中的數(shù)據(jù)順序和查找中的排列順序一致則獲得兩星
  3. 如果索引中的列包含查詢中全部列則獲得三星
    需要注意的是索引并不總是最好的工具,只有當(dāng)索引幫助存儲(chǔ)引擎快速查找到記錄帶來(lái)的好處大于其帶來(lái)的額外工作時(shí)激涤,索引才是有效的
    一般情況下:
    小表:全表掃描
    中表(數(shù)據(jù)量還不是很大):索引優(yōu)化
    大表(數(shù)據(jù)量超級(jí)大):高級(jí)技術(shù)比如分區(qū)等

索引類型

mysql中索引類型有很多,索引的實(shí)現(xiàn)方式是通過(guò)存儲(chǔ)引擎實(shí)現(xiàn)的倦踢,而不是服務(wù)器層實(shí)現(xiàn)的

B-TREE索引

一般我們沒(méi)有特別指明索引類型的時(shí)候,說(shuō)的索引應(yīng)該就是B-TREE索引辱挥,它使用B-TREE數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)數(shù)據(jù)的
因?yàn)樗饕怯纱鎯?chǔ)引擎實(shí)現(xiàn)的,所以不同的存儲(chǔ)引擎會(huì)通過(guò)不同的方式來(lái)使用B-TREE索引般贼,MYISAM使用前綴壓縮技術(shù)使得索引更小,同時(shí)采用物理位置引用被索引的行(也就是說(shuō)蕊梧,通過(guò)索引直接就可以找到對(duì)應(yīng)的數(shù)據(jù)行記錄)INNODB則按照原數(shù)據(jù)格式進(jìn)行存儲(chǔ),同時(shí)根據(jù)主鍵引用被所以的行(也就是說(shuō)通過(guò)索引首先會(huì)找到行的主鍵索引肥矢,然后通過(guò)主鍵索引找到具體的行)
B-TREE索引意味著所有存儲(chǔ)的數(shù)據(jù)記錄都是有順序的

b-tree數(shù)據(jù)結(jié)構(gòu).png

根據(jù)表的數(shù)據(jù)大小叠洗,B-TREE樹(shù)層級(jí)深度也將不同,其中每一個(gè)節(jié)點(diǎn)頁(yè)都包含了一個(gè)值以及左邊小于該值的子節(jié)點(diǎn)頁(yè)指針和大于該值的右節(jié)點(diǎn)頁(yè)指針十艾,也就是規(guī)定了該值的上線和下限,而葉子頁(yè)的指針指向的是具體的數(shù)據(jù)忘嫉,而不是其他的節(jié)點(diǎn)頁(yè)
在索引中案腺,順序是非常重要的一個(gè)因素,索引對(duì)多個(gè)值進(jìn)行排序的依據(jù)就是按照create table語(yǔ)句中定義索引時(shí)列的順序來(lái)實(shí)現(xiàn)的

B-TREE索引能使用的類型

全值匹配:所有列進(jìn)行匹配
匹配最左前綴:匹配索引的第一列
匹配列前綴:匹配某一列的值開(kāi)頭的部分
匹配范圍值:索引第一列范圍查找
精確匹配第一列劈榨,范圍匹配另外一列
因?yàn)樗饕龢?shù)中的節(jié)點(diǎn)是有順序的,所以除了按值查找之外拷姿,還可以對(duì)數(shù)據(jù)進(jìn)行order by排序操作,但是使用B-TREE索引也有一定的限制:
如果不是按照索引的最左列開(kāi)始查找跌前,將無(wú)法使用索引
不能跳過(guò)索引中的列
如果查詢中有某個(gè)列的范圍查詢陡舅,則其后面的列都將無(wú)法使用索引進(jìn)行查詢

hash索引

mysql索引是在存儲(chǔ)引擎層實(shí)現(xiàn)的,并沒(méi)有統(tǒng)一的標(biāo)準(zhǔn),不同的存儲(chǔ)引擎實(shí)現(xiàn)的索引方式是不同的
對(duì)于hash索引茎芋,只能精確匹配所有列的值蜈出,因?yàn)榇鎯?chǔ)引擎將會(huì)把生成hash索引的所有列的值用來(lái)構(gòu)建hash code
在mysql中,只有memory引擎顯示支持hash索引铡原,這也是它默認(rèn)的索引類型,memory引擎同時(shí)也是支持非唯一hash索引的燕刻,當(dāng)出現(xiàn)hash沖突時(shí),通過(guò)鏈表的方式解決沖突問(wèn)題
hash索引基于hash表實(shí)現(xiàn)的请唱,在它其中并不保存實(shí)際的值,而是保存hashcode->行的指針的鍵值對(duì)方式

hash索引數(shù)據(jù)結(jié)構(gòu).png

因此使用hash索引能快速的定位到某一行記錄十绑,但是它也存在某些限制:
hash索引只包含hash值與行指針酷勺,而不存儲(chǔ)字段值,所以不能使用索引中的值來(lái)避免讀取行
hash索引數(shù)據(jù)并不是按照索引值順序存儲(chǔ)的鸥印,也就無(wú)法使用排序
hash索引也不支持部分索引列匹配查找,因?yàn)閔ashcode是通過(guò)所有hash列生成出來(lái)的
hash值只支持等值比較查詢,包括=片择,in(),<=>(通過(guò)a <=> null,可以得出a為null的記錄) 不支持任何范圍查詢
訪問(wèn)hash索引的數(shù)據(jù)非匙止埽快,除非有很多hash沖突嘲叔,當(dāng)出現(xiàn)沖突時(shí),存儲(chǔ)引擎只能逐行進(jìn)行查找
如果hash沖突很多時(shí)锰什,維護(hù)起來(lái)代價(jià)也很高,應(yīng)該避免在選擇性比較低的列上建立hash索引
innodb引擎有一個(gè)特殊的功能叫做“自適應(yīng)hash索引”汁胆,當(dāng)innodb注意到某些索引值被頻繁的引用,它會(huì)在內(nèi)存中基于B-TREE索引之上再建立一個(gè)hash索引
如果某些存儲(chǔ)引擎不支持hash索引嫩码,我們需要?jiǎng)?chuàng)建自定義的hash索引,創(chuàng)建一個(gè)偽hash索引列铡恕,通過(guò)CRC32()對(duì)需要hash的列值計(jì)算hash,并在該列上創(chuàng)建索引
對(duì)于hash索引查找没咙,需要在where條件語(yǔ)句中加上hashcode比較和列值比較千劈,這樣是為了解決hash索引帶來(lái)的沖突

select url from t_urls where url_code = crc32(‘http://www.baidu.com’) and url = ‘http://www.baidu.com’;

這里如果發(fā)生了hash沖突,則根據(jù)url列值進(jìn)行查找
上面創(chuàng)建偽hashcode索引列采用的是crc32算法墙牌,生成一個(gè)32位的數(shù)字,但是通常64位數(shù)字hash沖突會(huì)更少喜滨,可以自己定義一個(gè)算法:

select conv(right(md5('http://www.baidu.com'), 16), 16, 10);

如果語(yǔ)句中的索引列不是獨(dú)立的,那么這條語(yǔ)句就不能使用該列索引棒口,也就是說(shuō)索引列不能作為表達(dá)式的一部分或者不能作為函數(shù)的參數(shù)

select acter_id from actor where acter_id +1 = 5;
select ... where to_days(current_date) – to_days(date_col)<= 10

對(duì)于長(zhǎng)度很長(zhǎng)的列,創(chuàng)建索引時(shí)可以采用類似hash索引那樣的无牵,自己建一個(gè)偽hashcode列厂抖,手動(dòng)維護(hù)這個(gè)列,通過(guò)列值計(jì)算該列對(duì)應(yīng)的數(shù)字值并作為hash索引
以u(píng)rl列舉例忱辅,如果直接使用url,則整個(gè)列字段的字符串太長(zhǎng)墙懂,占據(jù)太多空間,我們選擇為url創(chuàng)建一個(gè)url_code,用來(lái)計(jì)算crc32(url)得到的數(shù)字

create table urls {
    id int unsigned not null auto_increment,
    url varchar(255) not null,
    url_code int unsigned not null default 0
    primary key(id)
}

在插入或者更新url時(shí)碧库,通過(guò)觸發(fā)器重新計(jì)算url_code的值

delimiter //
create trigger urls_insert_trigger before insert on urls for each row begin 
set new.url_code = crc32(new.url);
end;
//
create trigger urls_update_trigger before update on urls for each row begin 
set new.url_code = crc32(new.url);
end;
//
delimiter;

通過(guò)偽hashcode列與該列值來(lái)精確查詢某一條記錄

select * from urls where url_code = crc32(‘http://www.baidu.com’) and url = ‘http://www.baidu.com’;

全文索引

全文索引是一種特殊類型的索引,它查找的是文本中的關(guān)鍵字谈为,而不是直接比較索引中的值,它與其他幾種類型的索引匹配方式完全不一樣伞鲫,它存在許多需要注意的細(xì)節(jié):如停用詞、詞干秕脓、復(fù)數(shù)、布爾搜索等吠架,更加類似于搜索引擎要干的事情

前綴索引

通過(guò)比較列選擇性和索引選擇性來(lái)決定前綴的長(zhǎng)度,對(duì)于mysql來(lái)說(shuō)傍药,不允許對(duì)text/blob列全值進(jìn)行索引,但是我們可以通過(guò)在查詢時(shí)指定使用前綴來(lái)優(yōu)化此類查詢拣挪,比如排序時(shí),避免磁盤臨時(shí)表排序
選擇性:不重復(fù)的索引值和數(shù)據(jù)表記錄總數(shù)的比值

select count(*) as count, city as city from t_city group by city order by city desc limit 10;

上面這條語(yǔ)句記錄了每一個(gè)城市出現(xiàn)的重復(fù)次數(shù)

select count(*) as count, left(city, 3) as pref from t_city group by pref order by pref desc limit 10;

還有一種選擇方式:計(jì)算列平均選擇性菠劝,并使前綴選擇性接近列選擇性

select count(distinct city) / count(*) from t_city;
select count(distinct left(city, 3)) / count(*) from t_city
前綴索引的創(chuàng)建方式

alter table sakila.city_demo add key city(7)
這樣就在sakila.city_demo表中創(chuàng)建了一個(gè)city前綴索引睁搭,索引長(zhǎng)度為7個(gè)字符,
使用前綴索引的缺點(diǎn)是:前綴索引不能用來(lái)做order by 和group by操作园骆,也無(wú)法用于作覆蓋掃描

后綴索引

還有一種是“反向索引”,針對(duì)像url這種類型的字符串列而言的遇伞,使用后綴來(lái)進(jìn)行索引效果更佳,但是mysql本身并不支持后綴索引這種方式,所以我們可以通過(guò)將保存的url字符串反向存入數(shù)據(jù)庫(kù)并創(chuàng)建前綴索引的方式來(lái)實(shí)現(xiàn)所謂的后綴索引

選擇合適的索引順序

在B-TREE索引中秋麸,索引列的順序意味著索引從最左列進(jìn)行排序,經(jīng)驗(yàn)法則告訴我們可以將選擇性高的放在前面灸蟆,當(dāng)不需要考慮排序和分組時(shí),將選擇性高的索引列放在前面通常是非常好的
我們需要對(duì)多個(gè)列計(jì)算每個(gè)列對(duì)應(yīng)的選擇性,然后做出決策

select count(distinct staff_id) / count(*) as staff_id_selectivity,
count(distinct custom_id) /count(*) as custom_id_selectivity, count(*) from payment \G;
列選擇性.png

根據(jù)查詢結(jié)果來(lái)看霎迫,應(yīng)該將custom_id放在索引列staff_id前面
順序的索引會(huì)造成的潛在問(wèn)題:
在高并發(fā)工作時(shí)帘靡,innoDB按主鍵順序插入可能會(huì)引起明顯的間隙鎖爭(zhēng)用

聚簇索引

聚簇索引其實(shí)是一種數(shù)據(jù)結(jié)構(gòu),保存了B-TREE索引和數(shù)據(jù)行描姚,數(shù)據(jù)表中的數(shù)據(jù)記錄都保存在葉子頁(yè)上,但是節(jié)點(diǎn)頁(yè)只包含了索引列
聚簇表示數(shù)據(jù)行與相鄰的鍵值緊湊的存儲(chǔ)在一起,

聚簇索引數(shù)據(jù)結(jié)構(gòu).png

在innoDB數(shù)據(jù)庫(kù)中筒扒,通過(guò)主鍵索引列來(lái)聚簇?cái)?shù)據(jù)記錄,也就是說(shuō)花墩,在innoDB聚簇索引中,節(jié)點(diǎn)頁(yè)上保存的是行主鍵冰蘑,如果沒(méi)有主鍵列,innoDB會(huì)選擇一個(gè)非空索引代替懂缕,如果也沒(méi)有這樣的索引王凑,innoDB會(huì)創(chuàng)建一個(gè)隱式的主鍵來(lái)進(jìn)行聚簇
在innodb中,沒(méi)有被用來(lái)做聚簇的索引索烹,被稱為是二級(jí)索引,在索引中保存的并不是物理行的位置百姓,而是行記錄的主鍵,需要根據(jù)二級(jí)索引找到行主鍵之后再到聚簇B-TREE中查找指定的行記錄
myisam引擎主鍵與其他索引實(shí)現(xiàn)相同垒拢,主鍵只是一個(gè)名稱為PRIMARY的非空索引。
myisam存儲(chǔ)數(shù)據(jù)就是按照數(shù)據(jù)的插入順序保存的求类,表存儲(chǔ)結(jié)構(gòu)的葉子節(jié)點(diǎn)上保存了當(dāng)前索引列值和物理行所在的位置
innodb通過(guò)B-TREE結(jié)構(gòu)保存數(shù)據(jù)表行的所有列記錄,二級(jí)索引通過(guò)保存主鍵值椿猎,在根據(jù)主鍵值在B-TREE結(jié)構(gòu)中查找物理行數(shù)據(jù)信息

聚集的數(shù)據(jù)有哪些優(yōu)點(diǎn)

  1. 可以把相關(guān)的數(shù)據(jù)保存在一起惶岭,這樣在查找記錄時(shí)可以從磁盤上讀取少量的頁(yè)就能查到結(jié)果
  2. 訪問(wèn)數(shù)據(jù)更快按灶,聚簇索引將索引和數(shù)據(jù)都保存在同一個(gè)B-TREE中,因此從聚簇索引獲取數(shù)據(jù)比非聚簇索引獲取數(shù)據(jù)要快
  3. 使用覆蓋索引掃描的查詢鸯旁,可以直接使用頁(yè)節(jié)點(diǎn)的主鍵值,無(wú)需再根據(jù)主鍵查找數(shù)據(jù)
    聚簇索引的缺點(diǎn)
    聚簇索引最大限度的提高了I/O密集型應(yīng)用的性能羡亩,但如果數(shù)據(jù)全部都放在內(nèi)存中危融,那么訪問(wèn)的順序就沒(méi)那么重要了
  4. 插入速度嚴(yán)重依賴于插入順序,按照主鍵的順序插入是加載數(shù)據(jù)到INNODB表中速度最快的方式
  5. 更新聚簇索引列的代價(jià)很高吉殃,因?yàn)闀?huì)強(qiáng)制每一個(gè)被更新的行移動(dòng)到新的位置
    4. 基于聚簇索引的表在插入新行,或者主鍵被更新導(dǎo)致需要移動(dòng)行的時(shí)候蛋勺,可能面臨頁(yè)分裂的問(wèn)題
  6. 聚簇索引可能導(dǎo)致全表掃描變慢,尤其是行比較稀疏的時(shí)候抱完,或者頁(yè)分裂導(dǎo)致數(shù)據(jù)存儲(chǔ)不連續(xù)的時(shí)候
  7. 二級(jí)索引可能比想象的大,因?yàn)槎?jí)索引的葉子節(jié)點(diǎn)包含了引用行的主鍵列
  8. 二級(jí)索引訪問(wèn)需要兩次索引查找碉怔,找主鍵、找數(shù)據(jù)
延遲查詢

對(duì)于某些查詢撮胧,可以通過(guò)延遲查詢來(lái)優(yōu)化
explain select * from products where actor = ‘sean carrey’ and title like ‘%apollo%’\G
其中actor 與title 列建立了索引
這里無(wú)法對(duì)查詢進(jìn)行索引覆蓋,因?yàn)椴樵兊牧袨槿苛星凵叮淮嬖谌魏我粋€(gè)索引可以覆蓋所有列
改為延遲加載,添加索引覆蓋列(actor, title, prod_id)

explain select * from products inner join (
select prod_id from products where actor = ‘sean carrey’ and title like ‘%apollo%’)as t1 on (t1.prod_id = products.prod_id)

上面子查詢采用索引覆蓋墓怀,過(guò)濾prod_id,然后根據(jù)prod_id再到記錄中查找

覆蓋索引

如果一個(gè)索引包含所有需要查詢的字段的值卫键,那么我們就稱之為覆蓋索引

覆蓋索引的好處

  1. 索引條目通常遠(yuǎn)小于數(shù)據(jù)行大小,所以如果只需要讀取索引永罚,那mysql就會(huì)極大的減少數(shù)據(jù)訪問(wèn)量
  2. 因?yàn)樗饕前凑樟兄淀樞虼鎯?chǔ)的,所以順序查詢會(huì)比隨機(jī)從磁盤讀取數(shù)據(jù)的I/O要少的多
  3. 一些存儲(chǔ)引擎如MYISAM在內(nèi)存中只緩存索引呢袱,數(shù)據(jù)則依賴于具體OS來(lái)緩存,因此訪問(wèn)數(shù)據(jù)意味著還需要一次系統(tǒng)調(diào)用羞福,采用覆蓋索引則減少了這樣的系統(tǒng)調(diào)用
  4. 針對(duì)INNODB的聚簇索引,覆蓋索引可以杜絕二級(jí)索引根據(jù)主鍵值查找數(shù)據(jù)行記錄
    覆蓋索引必須要存儲(chǔ)索引列的值卖陵,而hash索引、空間索引泪蔫、全文索引都不存儲(chǔ)索引列的值,所以mysql只能使用b-tree索引做覆蓋索引
    當(dāng)發(fā)起一個(gè)索引覆蓋查詢時(shí)撩荣,通過(guò)explain分析語(yǔ)句會(huì)看到extra Using index,這里的extra表示的是檢索數(shù)據(jù)的方式,需要與type進(jìn)行區(qū)分餐曹,type index表示在對(duì)結(jié)果集進(jìn)行排序時(shí)使用到了索引
    如果查詢的列沒(méi)有被索引覆蓋敌厘,也就是無(wú)法使用索引覆蓋查詢時(shí),explain查詢分析出來(lái)extra Using where
    對(duì)于下面這條語(yǔ)句:
explain select * from products where actor=’seny carrey’ and title like ‘%apollo%’\G

存在兩個(gè)問(wèn)題導(dǎo)致它無(wú)法使用覆蓋索引:

  1. 沒(méi)有任何一個(gè)索引能夠覆蓋這個(gè)查詢俱两,因?yàn)閺谋碇羞x擇了所有列,而沒(méi)有任何索引覆蓋了所有列
  2. mysql不能在索引中執(zhí)行l(wèi)ike操作锋华,只是允許使用左前綴匹配的方式和一些簡(jiǎn)單的值比較,上面的查詢語(yǔ)句可以通過(guò)延遲關(guān)聯(lián)來(lái)解決:
select * from product inner join(
    select prod_id from product where actor=’seny carrey’ and title like ‘a(chǎn)pollo%’
) as t1 on t1.prod_id = product.prod_id\G

使用索引掃描做排序

排序有兩種方式:直接通過(guò)排序毯焕、按索引順序掃描,如果explain出來(lái)的結(jié)果中的type為index,則表示使用到了索引掃描來(lái)做排序
orderby子句的列順序必須與索引列定義的順序完全一致(也就是說(shuō)按照多個(gè)列進(jìn)行排序婆咸,要么都升序,要么都降序)尚骄,因?yàn)閙ysql是按照索引順序來(lái)組織記錄順序的,而order by 如果打破了這種規(guī)則那么就必須使用文件排序
如果查詢關(guān)聯(lián)多張表倔丈,則只有當(dāng)order by子句引用的字段全部為第一個(gè)表憨闰,才能使用索引做排序
還有一種情況就是如果索引前導(dǎo)列(where語(yǔ)句或者join子句中包含的索引第一列)設(shè)置為常量時(shí)鹉动,就可以使用索引進(jìn)行排序,比如:
(rental_date,inventory_id,customer_id)為一個(gè)組合索引,則語(yǔ)句

select rental_id,staff_id from sakila.rental where rental_date=’2005-05-25’ order by inventory_id,customer_id

可以使用索引進(jìn)行排序泽示,雖然order by 子句不滿足索引的最左前綴要求,也可以用于查詢排序械筛,因?yàn)樗饕谝涣斜辉O(shè)置成為了常量

下面列出不能使用索引做排序的查詢

  1. 使用兩種不同的排序方向,但是索引列都是正序排列
    where rental_date=2005-05-25’ order by inventory_id desc,customer_id asc;
  2. 引用不存在與索引中的列
    where rental_date=2005-05-25’ order by inventory_id,staff_id
  3. where與order by中的列無(wú)法組合成索引的最左前綴
    where rental_date=’2005-05-25’ order by customer_id
  4. 查詢?cè)谒饕械牡谝涣袨榉秶樵儣l件埋哟,所以mysql無(wú)法使用其他的索引列
    where rental_date > ‘2005-05-25’ order by inventory_id,customer_id
  5. 索引列上存在多個(gè)等值條件厌丑,對(duì)于查詢來(lái)說(shuō)其實(shí)就相當(dāng)于范圍查詢
    where rental_date = ‘2005-05-25’ and inventory_id in(1,2) order by customer_id

壓縮(前綴壓縮)索引

myisam使用前綴壓縮索引減少索引的大小,從而讓更多的索引能放入內(nèi)存怒竿,默認(rèn)只壓縮字符串,但是也可以配置壓縮整數(shù)
myisam壓縮每個(gè)索引塊的方法是耕驰,先完全保存索引塊的第一個(gè)值,然后將其他值和第一個(gè)值進(jìn)行比較得到相同的前綴的字節(jié)數(shù)和不同的后綴朦肘,把這部分存儲(chǔ)起來(lái)即可,比如:索引塊中第一個(gè)值為perform媒抠,第二個(gè)值為performance,那么第二個(gè)值的前綴壓縮后存儲(chǔ)的是7,ance這樣的形式
前綴索引無(wú)法通過(guò)二分查找只能從頭開(kāi)始掃描趴生,正序的掃描速度還不錯(cuò),但反序就不是很好了

冗余索引和重復(fù)索引

重復(fù)索引苍匆,具有相同類型、按照相同順序的索引叔汁,應(yīng)該避免,發(fā)現(xiàn)后立即刪除
冗余索引据块,(A,B)為索引,再創(chuàng)建索引(A)就是冗余索引瑰钮,因?yàn)锳索引只是AB索引的前綴索引,因此索引(AB)也可以當(dāng)做(A)來(lái)算
默認(rèn)情況下在創(chuàng)建innodb二級(jí)索引時(shí)浪谴,主鍵索引已經(jīng)默認(rèn)添加到該索引上了因苹,例如(A, ID)其中id為主鍵索引
冗余索引必須是相同的類型,其他類型的索引扶檐,比如hash索引或者全文索引頁(yè)不會(huì)是B-TREE索引的冗余索引

索引和鎖

索引可以讓查詢鎖定更少的行,innodb只有在訪問(wèn)行的時(shí)候才會(huì)對(duì)其加鎖款筑,而索引能夠減少innodb訪問(wèn)的行數(shù),從而減少鎖的數(shù)量奈梳,但這只有在存儲(chǔ)引擎層過(guò)濾掉所有不需要的行時(shí)才有效

支持多種過(guò)濾條件

在有更多不同值的列上創(chuàng)建索引的選擇性會(huì)更好,在檢索時(shí)攘须,我們可以將查詢用的多的列加入到索引中,對(duì)于索引前綴列不需要進(jìn)行條件過(guò)濾時(shí)于宙,通過(guò)in指定列值,IN的方式對(duì)查詢檢索是有效的至会,但是對(duì)order by則是無(wú)效的,比如存在(sex,country)這樣的索引奉件,當(dāng)我們需要使用到該索引時(shí),但又不需要對(duì)性別做出限制瓶蚂,那么我們可以通過(guò)and sex in (‘m’,’f’)的方式讓mysql選擇該列索引

避免多個(gè)范圍條件

針對(duì)這兩種查詢語(yǔ)句:

select actor_id from actor where actor_id > 45;
select actor_id from actor where actor_id in (1,4,49);

這兩種查詢語(yǔ)句的執(zhí)行效率是不同的,對(duì)于范圍查詢窃这,mysql是無(wú)法使用范圍列后面的其他索引列了,但是對(duì)于多個(gè)等值條件查詢,則沒(méi)有這個(gè)限制

維護(hù)索引和表

找到并修復(fù)索引表

通過(guò)check table來(lái)檢查是否發(fā)生了表?yè)p壞庇勃,并通過(guò)repair table來(lái)修復(fù)表;但是如果存儲(chǔ)引擎不支持該命令馆铁,也可以通過(guò)alter table 重建表來(lái)達(dá)到修復(fù)目的
alter table innodb_tbl ENGINE=INNODB

更新索引統(tǒng)計(jì)信息

查詢優(yōu)化器通過(guò)兩個(gè)API來(lái)了解存儲(chǔ)引擎的索引值分布锅睛,通過(guò)這兩個(gè)API的結(jié)果來(lái)決定使用哪個(gè)索引進(jìn)行查詢優(yōu)化
records_in_range();傳入兩個(gè)邊界值計(jì)算之間的記錄數(shù)
info();返回各種類型的數(shù)據(jù)包括索引基數(shù)(通過(guò)show index from table)
如果統(tǒng)計(jì)信息不準(zhǔn)確,那么定會(huì)影響到查詢優(yōu)化器的優(yōu)化策略现拒,通過(guò)analyze table重新生成統(tǒng)計(jì)信息

數(shù)據(jù)碎片類型

行碎片:數(shù)據(jù)行被存儲(chǔ)在多個(gè)地方的多個(gè)片段中
行間碎片:邏輯上順序的頁(yè),在磁盤上不是順序的
剩余空間碎片:數(shù)據(jù)頁(yè)中大量的空余空間
通過(guò)optimize table 或者導(dǎo)出再導(dǎo)入的方式來(lái)重新整理數(shù)據(jù)印蔬,對(duì)于不支持該命令的存儲(chǔ)引擎,可以通過(guò)alter table tablename engine=<engine>來(lái)進(jìn)行優(yōu)化
每種存儲(chǔ)引擎實(shí)現(xiàn)索引統(tǒng)計(jì)信息的方式不同侥猬,所以需要進(jìn)行analyze table的頻率也不同:

  1. memory引擎根本不存儲(chǔ)索引統(tǒng)計(jì)信息
  2. myisam引擎將索引統(tǒng)計(jì)信息存儲(chǔ)在磁盤中,analyze table需要進(jìn)行一次全索引掃描來(lái)計(jì)算索引基數(shù)
  3. 直到mysql5.5鹃锈,innodb也不在磁盤存儲(chǔ)索引統(tǒng)計(jì)信息,而是通過(guò)隨機(jī)的索引訪問(wèn)進(jìn)行評(píng)估仪召,并將估算結(jié)果存在內(nèi)存中

mysql執(zhí)行狀態(tài)

通過(guò)show full processlist來(lái)查看mysql當(dāng)前處在哪一個(gè)狀態(tài)
sleep 線程正等待客戶端發(fā)起查詢請(qǐng)求
locked 在mysql服務(wù)層里,該線程正在等待表鎖
Analyzing and statistics 線程正在搜集存儲(chǔ)引擎的統(tǒng)計(jì)信息扔茅,并生成查詢執(zhí)行計(jì)劃
query 線程正在查詢
Copying to tmp table [on disk],線程正在執(zhí)行查詢,并將結(jié)果復(fù)制到一個(gè)臨時(shí)表中召娜,這種狀態(tài)要么是在group by操作,要么是在文件排序操作玖瘸,如果這個(gè)狀態(tài)后面還有on disk ,則表示mysql正在把一個(gè)內(nèi)存臨時(shí)表放到磁盤
sorting result 線程正在進(jìn)行排序
Sending data 這個(gè)狀態(tài)有多重可能雅倒,有可能是線程之間在進(jìn)行數(shù)據(jù)傳輸,或者正在生成結(jié)果集蔑匣,或者向客戶端返回?cái)?shù)據(jù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市裁良,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌价脾,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侨把,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡座硕,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)机隙,“玉大人,你說(shuō)我怎么就攤上這事有鹿。” “怎么了葱跋?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)娱俺。 經(jīng)常有香客問(wèn)我,道長(zhǎng)荠卷,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任油宜,我火速辦了婚禮,結(jié)果婚禮上慎冤,老公的妹妹穿的比我還像新娘。我一直安慰自己蚁堤,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著熟空,像睡著了一般。 火紅的嫁衣襯著肌膚如雪息罗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 48,954評(píng)論 1 283
  • 那天迈喉,我揣著相機(jī)與錄音,去河邊找鬼挨摸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛得运,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锅移,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼置逻!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起券坞,我...
    開(kāi)封第一講書(shū)人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恨锚,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體眠冈,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年蜗顽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了雨让。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡栖忠,死狀恐怖贸街,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情薛匪,我是刑警寧澤,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布逸尖,位于F島的核電站,受9級(jí)特大地震影響娇跟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜太颤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吃谣。 院中可真熱鬧,春花似錦做裙、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至悍缠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間飞蚓,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工趴拧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人著榴。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像脑又,于是被迫代替她去往敵國(guó)和親锐借。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 索引基礎(chǔ) 索引的類型 B-Tree索引 當(dāng)人們談?wù)撍饕龝r(shí)钞翔,如果沒(méi)有特別指明類型席舍,那多半說(shuō)的是B-Tree索引。存儲(chǔ)...
    coolcao閱讀 466評(píng)論 1 3
  • 1.b-樹(shù)索引 索引首先要回顧一下b樹(shù)b+樹(shù)的特點(diǎn)和區(qū)別俺亮,數(shù)據(jù)庫(kù)引擎用b+樹(shù)的好處有查詢時(shí)間比較穩(wěn)定,b+樹(shù)比較適...
    j4fan閱讀 381評(píng)論 0 0
  • 創(chuàng)建高性能索引 索引是什么脚曾?有什么作用? 索引是存儲(chǔ)引擎用于快速找到記錄的一種數(shù)據(jù)結(jié)構(gòu) 如書(shū)的目錄索引一般本讥,數(shù)據(jù)庫(kù)...
    esrever閱讀 650評(píng)論 0 0
  • 5.1 索引基礎(chǔ) 在MySQL中,存儲(chǔ)引擎在使用索引時(shí)拷沸,先找到索引的對(duì)應(yīng)值,然后根據(jù)匹配的索引找到對(duì)應(yīng)的數(shù)據(jù)行撞芍。假...
    YaleWei閱讀 523評(píng)論 0 0
  • 我一輩子幸福感最強(qiáng)烈的時(shí)候,是什么時(shí)候序无?主要是兩段時(shí)光验毡。一段是談戀愛(ài)的時(shí)候帝嗡。 我在上初中的時(shí)候,就暗戀一個(gè)女生哟玷,她...
    續(xù)寫不盡de未來(lái)閱讀 180評(píng)論 0 4