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

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

期待.jpg

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

索引的作用

  1. 可以快速根據(jù)索引查找指定的記錄
  2. 可以根據(jù)索引對(duì)記錄進(jìn)行排序,可以用來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ǔ)引擎快速查找到記錄帶來的好處大于其帶來的額外工作時(shí),索引才是有效的
    一般情況下:
    小表:全表掃描
    中表(數(shù)據(jù)量還不是很大):索引優(yōu)化
    大表(數(shù)據(jù)量超級(jí)大):高級(jí)技術(shù)比如分區(qū)等

索引類型

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

B-TREE索引

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

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

根據(jù)表的數(shù)據(jù)大小,B-TREE樹層級(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語句中定義索引時(shí)列的順序來實(shí)現(xiàn)的

B-TREE索引能使用的類型

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

hash索引

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

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

因此使用hash索引能快速的定位到某一行記錄,但是它也存在某些限制:
hash索引只包含hash值與行指針,而不存儲(chǔ)字段值,所以不能使用索引中的值來避免讀取行
hash索引數(shù)據(jù)并不是按照索引值順序存儲(chǔ)的,也就無法使用排序
hash索引也不支持部分索引列匹配查找,因?yàn)閔ashcode是通過所有hash列生成出來的
hash值只支持等值比較查詢,包括=,in(),<=>(通過a <=> null,可以得出a為null的記錄) 不支持任何范圍查詢
訪問hash索引的數(shù)據(jù)非???,除非有很多hash沖突,當(dāng)出現(xiàn)沖突時(shí),存儲(chǔ)引擎只能逐行進(jìn)行查找
如果hash沖突很多時(shí),維護(hù)起來代價(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索引列,通過CRC32()對(duì)需要hash的列值計(jì)算hash,并在該列上創(chuàng)建索引
對(duì)于hash索引查找,需要在where條件語句中加上hashcode比較和列值比較,這樣是為了解決hash索引帶來的沖突

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);

如果語句中的索引列不是獨(dú)立的,那么這條語句就不能使用該列索引,也就是說索引列不能作為表達(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è)列,通過列值計(jì)算該列對(duì)應(yīng)的數(shù)字值并作為hash索引
以u(píng)rl列舉例,如果直接使用url,則整個(gè)列字段的字符串太長(zhǎng),占據(jù)太多空間,我們選擇為url創(chuàng)建一個(gè)url_code,用來計(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í),通過觸發(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;

通過偽hashcode列與該列值來精確查詢某一條記錄

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

全文索引

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

前綴索引

通過比較列選擇性和索引選擇性來決定前綴的長(zhǎng)度,對(duì)于mysql來說,不允許對(duì)text/blob列全值進(jìn)行索引,但是我們可以通過在查詢時(shí)指定使用前綴來優(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;

上面這條語句記錄了每一個(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)是:前綴索引不能用來做order by 和group by操作,也無法用于作覆蓋掃描

后綴索引

還有一種是“反向索引”,針對(duì)像url這種類型的字符串列而言的,使用后綴來進(jìn)行索引效果更佳,但是mysql本身并不支持后綴索引這種方式,所以我們可以通過將保存的url字符串反向存入數(shù)據(jù)庫(kù)并創(chuàng)建前綴索引的方式來實(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é)果來看,應(yīng)該將custom_id放在索引列staff_id前面
順序的索引會(huì)造成的潛在問題:
在高并發(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ù)中,通過主鍵索引列來聚簇?cái)?shù)據(jù)記錄,也就是說,在innoDB聚簇索引中,節(jié)點(diǎn)頁(yè)上保存的是行主鍵,如果沒有主鍵列,innoDB會(huì)選擇一個(gè)非空索引代替,如果也沒有這樣的索引,innoDB會(huì)創(chuàng)建一個(gè)隱式的主鍵來進(jìn)行聚簇
在innodb中,沒有被用來做聚簇的索引,被稱為是二級(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通過B-TREE結(jié)構(gòu)保存數(shù)據(jù)表行的所有列記錄,二級(jí)索引通過保存主鍵值,在根據(jù)主鍵值在B-TREE結(jié)構(gòu)中查找物理行數(shù)據(jù)信息

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

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

對(duì)于某些查詢,可以通過延遲查詢來優(yōu)化
explain select * from products where actor = ‘sean carrey’ and title like ‘%apollo%’\G
其中actor 與title 列建立了索引
這里無法對(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)

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

覆蓋索引

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

覆蓋索引的好處

  1. 索引條目通常遠(yuǎn)小于數(shù)據(jù)行大小,所以如果只需要讀取索引,那mysql就會(huì)極大的減少數(shù)據(jù)訪問量
  2. 因?yàn)樗饕前凑樟兄淀樞虼鎯?chǔ)的,所以順序查詢會(huì)比隨機(jī)從磁盤讀取數(shù)據(jù)的I/O要少的多
  3. 一些存儲(chǔ)引擎如MYISAM在內(nèi)存中只緩存索引,數(shù)據(jù)則依賴于具體OS來緩存,因此訪問數(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í),通過explain分析語句會(huì)看到extra Using index,這里的extra表示的是檢索數(shù)據(jù)的方式,需要與type進(jìn)行區(qū)分,type index表示在對(duì)結(jié)果集進(jìn)行排序時(shí)使用到了索引
    如果查詢的列沒有被索引覆蓋,也就是無法使用索引覆蓋查詢時(shí),explain查詢分析出來extra Using where
    對(duì)于下面這條語句:
explain select * from products where actor=’seny carrey’ and title like ‘%apollo%’\G

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

  1. 沒有任何一個(gè)索引能夠覆蓋這個(gè)查詢,因?yàn)閺谋碇羞x擇了所有列,而沒有任何索引覆蓋了所有列
  2. mysql不能在索引中執(zhí)行l(wèi)ike操作,只是允許使用左前綴匹配的方式和一些簡(jiǎn)單的值比較,上面的查詢語句可以通過延遲關(guān)聯(lián)來解決:
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

使用索引掃描做排序

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

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中的列無法組合成索引的最左前綴
    where rental_date=’2005-05-25’ order by customer_id
  4. 查詢?cè)谒饕械牡谝涣袨榉秶樵儣l件,所以mysql無法使用其他的索引列
    where rental_date > ‘2005-05-25’ order by inventory_id,customer_id
  5. 索引列上存在多個(gè)等值條件,對(duì)于查詢來說其實(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ǔ)起來即可,比如:索引塊中第一個(gè)值為perform,第二個(gè)值為performance,那么第二個(gè)值的前綴壓縮后存儲(chǔ)的是7,ance這樣的形式
前綴索引無法通過二分查找只能從頭開始掃描,正序的掃描速度還不錯(cuò),但反序就不是很好了

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

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

索引和鎖

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

支持多種過濾條件

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

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

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

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

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

維護(hù)索引和表

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

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

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

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

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

行碎片:數(shù)據(jù)行被存儲(chǔ)在多個(gè)地方的多個(gè)片段中
行間碎片:邏輯上順序的頁(yè),在磁盤上不是順序的
剩余空間碎片:數(shù)據(jù)頁(yè)中大量的空余空間
通過optimize table 或者導(dǎo)出再導(dǎo)入的方式來重新整理數(shù)據(jù),對(duì)于不支持該命令的存儲(chǔ)引擎,可以通過alter table tablename engine=<engine>來進(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)行一次全索引掃描來計(jì)算索引基數(shù)
  3. 直到mysql5.5,innodb也不在磁盤存儲(chǔ)索引統(tǒng)計(jì)信息,而是通過隨機(jī)的索引訪問進(jìn)行評(píng)估,并將估算結(jié)果存在內(nèi)存中

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

通過show full processlist來查看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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容