溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

MySQL中高效正確使用索引的方法

發(fā)布時(shí)間:2020-08-15 09:17:09 來源:億速云 閱讀:242 作者:小新 欄目:開發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)MySQL中高效正確使用索引的方法,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

實(shí)踐是檢驗(yàn)真理的唯一途徑,本篇只是站在索引使用的全局來定位的,你只需要通讀全篇并結(jié)合具體的例子,或回憶以往使用過的地方,對(duì)整體有個(gè)全面認(rèn)識(shí),并理解索引是如何工作的,就可以了。在后續(xù)使用索引,或者優(yōu)化索引時(shí),可以從這些方面出發(fā),進(jìn)一步來加深對(duì)索引正確高效的使用。

一、索引失效

索引失效,是一個(gè)老生常談的話題了。只要提到數(shù)據(jù)庫優(yōu)化、使用索引,都能一口氣說出一大堆索引失效的場(chǎng)景,什么不能用、什么不該用這類的話,在此,我就不再一一羅列啰嗦了。

索引失效,是指表中有字段創(chuàng)建了索引,由于sql語句書寫不當(dāng)導(dǎo)致索引失效的情況。

在sql語句中,將索引列作為表達(dá)式的一部分、參與函數(shù)/數(shù)學(xué)等運(yùn)算,將會(huì)導(dǎo)致索引失效。

例如,下面這個(gè)查詢無法使用age列的索引:

select id,name,age from t_user where age + 1 = 7;

很容易看出where中的表達(dá)式其實(shí)等價(jià)于age=8,但是MySQL無法自動(dòng)解析這個(gè)表達(dá)式,這完全是用戶行為。

(在上一篇文章中,我們知道MySQL先在索引上按值進(jìn)行查找,然后返回索引值對(duì)應(yīng)的數(shù)據(jù)行,一旦對(duì)索引列進(jìn)行運(yùn)算,則將無法正確的找到對(duì)應(yīng)的數(shù)據(jù)行,從而改為全表逐行掃描查詢對(duì)比)

二、前綴索引和索引選擇性

有時(shí)候?qū)?nèi)容很長(zhǎng)的列作為索引列,這將會(huì)讓索引變得很大而且很慢。如果非要在該列添加索引,解決策略就是上一篇文章提到過的模擬哈希索引。

通??梢运饕_始的部分字符,這樣可以大大節(jié)約索引空間,從而提高索引效率,但這樣也會(huì)降低索引的選擇性。

索引的選擇性是指,不重復(fù)的索引值(也稱為基數(shù))和表數(shù)據(jù)的記錄總數(shù)T的比值,范圍從1/T到1之間。索引的選擇性越高,則查詢效率越高,因?yàn)檫x擇性高的索引可以讓MySQL在查找時(shí)過濾掉更多的行。

唯一索引的選擇性為1,這是最好的索引選擇性,性能也是最好的。

對(duì)于BLOB、TEXT或很大的VARCHAR類型的列,作為查詢條件時(shí)(原則上是要避免這樣的操作,但有時(shí)總是情非得已),該列必須使用前綴索引,這樣來提高查詢性能。因?yàn)镸ySQL是不允許索引這些列的完整長(zhǎng)度的。

三、多列索引

多列索引,是指為每個(gè)列創(chuàng)立獨(dú)立的索引。

在SQL優(yōu)化時(shí),有人會(huì)采取“把where條件里面的列都建上索引”,希望能夠?qū)Σ樵冃阅苡兴鶅?yōu)化。但實(shí)際上這樣的優(yōu)化是非常錯(cuò)誤的,這樣一來最好的情況下也只能是“一星”索引,其性能比起真正最優(yōu)的索引可能差幾個(gè)數(shù)據(jù)級(jí)。有時(shí)如果無法設(shè)計(jì)一個(gè)“三星”索引,那么不如忽略掉where子句,集中精力優(yōu)化索引列的順序,或者創(chuàng)建一個(gè)全覆蓋索引。

三星索引:在Lahdenmaki和Leach編寫的Relational Database Index Design and the Optimizers一書中,提到如何評(píng)價(jià)一個(gè)索引是否適合某個(gè)查詢的“三星系統(tǒng)”:索引將相關(guān)的記錄放到一起則獲得“一星”;如果索引中的數(shù)據(jù)順序和查找中的排序順序一致則獲得“二星”;如果索引中的列包含了查詢中需要的全部列則獲得“三星”。

在多個(gè)列上建立獨(dú)立的單列索引,大部分情況下并不能提高M(jìn)ySQL的查詢性能。這也是將其錯(cuò)誤的做法。

MySQL5.0及之后版本引入了索引合并策略,一定程度上可以使用表上的多個(gè)單列索引來定位指定的行。更早的MySQL只能使用其中某一個(gè)單列索引,然而這個(gè)情況下沒有哪一個(gè)獨(dú)立的單列索引是非常有效的。

索引合并策略有時(shí)候是一種優(yōu)化的結(jié)果,但實(shí)際上更多時(shí)候說明了表上的索引建的很糟糕:

1)當(dāng)出現(xiàn)對(duì)多個(gè)索引做相交操作時(shí)(通常由多個(gè)AND條件),通常意味著需要一個(gè)包含所有相關(guān)列的多列索引,而不是多個(gè)獨(dú)立的單列索引。

2)當(dāng)需要對(duì)多個(gè)索引做聯(lián)合操作室(通常有多個(gè)OR條件),通常需要耗費(fèi)大量的CPU和內(nèi)存資源在算法的緩存、排序和合并操作上。特別是當(dāng)其中有些索引的選擇性不高,需要合并掃描返回的大量數(shù)據(jù)的時(shí)候。

3)優(yōu)化器不會(huì)把這些計(jì)算到“查詢成本”中,優(yōu)化器只關(guān)心隨機(jī)頁面讀取。這會(huì)使得查詢的成本被“低估”,導(dǎo)致該執(zhí)行計(jì)劃還不如直接走全表掃描。這樣做不但會(huì)消耗更多的CPU和內(nèi)存資源,還可能會(huì)影響查詢的并發(fā)性,但如果是單獨(dú)運(yùn)行這樣的查詢,則往往會(huì)忽略對(duì)并發(fā)性的影響。

如果在執(zhí)行計(jì)劃EXPLAIN中看到索引合并,應(yīng)該好好檢查一下查詢和表的結(jié)構(gòu),看是不是已經(jīng)是最優(yōu)的。也可以通過參數(shù)optimizer_switch來關(guān)閉索引合并功能,也可以使用IGNORE INDEX提示讓優(yōu)化器忽略掉某些索引。

對(duì)于多列索引,只要查詢的條件中用到了最左邊的列,索引一般就不會(huì)失效。

舉例說明如下:

表t_user創(chuàng)建了(id,name)的多列索引,具體如下:

mysql> show create table t_user;
+--------+---------------+
| Table | Create Table |
+--------+---------------+
| t_user | CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
KEY `idx` (`id`,`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 |
+--------+-----------------------------------------+
1 row in set

根據(jù)id進(jìn)行查詢,具體如下:

mysql> explain select * from t_user where id = 1;
+----+-------------+--------+------------+------+---------------+-----+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref  | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+-----+---------+-------+------+----------+-------+
| 1 | SIMPLE   | t_user | NULL    | ref | idx      | idx | 4    | const |  1 |   100 | NULL |
+----+-------------+--------+------------+------+---------------+-----+---------+-------+------+----------+-------+
1 row in set

從執(zhí)行計(jì)劃中的type可以看出,索引是有效的。但如果根據(jù)name進(jìn)行查詢,則索引將會(huì)失效(全表掃描),如下:

mysql> explain select * from t_user where name = 'xcbeyond';
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra    |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE   | t_user | NULL    | ALL | NULL     | NULL | NULL  | NULL |  7 |  14.29 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set

四、選擇合適的索引列順序

索引列順序?qū)嵲谑欠浅V匾?。正確的順序依賴于使用該索引的查詢,并且同時(shí)需要考慮如何更好的滿足排序和分組的需要(只用于B-Tree索引,哈?;蛘咂渌饕鎯?chǔ)數(shù)據(jù)并不是順序存儲(chǔ))。

在一個(gè)多列B-Tree索引中,索引列的順序意味著索引首先按照最左列進(jìn)行排列。所以索引可以按照升序或者降序進(jìn)行掃描,以滿足符合列順序的order by,group by和distinct等子句的查詢需求。

所以多列索引列的順序至關(guān)重要。對(duì)于如何選擇索引的列順序有一個(gè)經(jīng)驗(yàn)法則:將選擇性最高的索引放在索引的最前列。在某些場(chǎng)景這個(gè)經(jīng)驗(yàn)時(shí)非常有用,但是通常不如避免隨機(jī)IO和排序那么重要,考慮問題需要更全面。

當(dāng)不需要考慮排序和分組時(shí),將選擇性最高的列放在前面通常是很好的。這時(shí)候索引的作用只是用于優(yōu)化where條件的查找。這種情況下,這樣設(shè)計(jì)的索引確實(shí)能夠最快的過濾出需要的行,對(duì)于在where的子句中只是用了索引部分前綴列的查詢來說選擇性也更高。然而性能不只是依賴于所有索引列的選擇性,也和查詢條件的具體值有關(guān),也就是和值的分布有關(guān)(需要根據(jù)那些運(yùn)行頻率最高的查詢來調(diào)整索引列的順序,讓這種情況下的索引列的選擇性最高)。

五、聚簇索引

聚簇索引并不是一種單獨(dú)的索引類型,而是一種數(shù)據(jù)存儲(chǔ)方式,將數(shù)據(jù)存儲(chǔ)與索引放到了一塊,找到索引頁就找到了數(shù)據(jù)。具體的細(xì)節(jié)依賴于其實(shí)現(xiàn)方式,但InnoDB的聚簇索引實(shí)際上在同一個(gè)結(jié)構(gòu)中保存了B-Tree索引和數(shù)據(jù)行。

非聚簇索引:將數(shù)據(jù)存儲(chǔ)與索引分開存儲(chǔ),索引結(jié)構(gòu)的葉子節(jié)點(diǎn)指向了數(shù)據(jù)的對(duì)應(yīng)行。當(dāng)需要訪問數(shù)據(jù)時(shí)(通過索引訪問數(shù)據(jù)),在內(nèi)存中直接搜索索引,然后通過索引找到磁盤相應(yīng)數(shù)據(jù),這也就是為什么索引不在key buffer命中時(shí),速度慢的原因。

當(dāng)表有聚簇索引時(shí),它的數(shù)據(jù)行實(shí)際上存放在索引的葉子頁中。“聚簇”表示數(shù)據(jù)行和相鄰的鍵值緊湊的存儲(chǔ)在一起。因?yàn)闊o法同時(shí)把數(shù)據(jù)行存放在兩個(gè)不同的地方,所以一個(gè)表只能有一個(gè)聚簇索引。

聚簇索引的設(shè)定:

默認(rèn)為主鍵。如果沒有定義主鍵,InnoDB會(huì)選擇一個(gè)唯一的非空索引代替。如果沒有這樣的索引,InnoD會(huì)隱式定義一個(gè)主鍵來作為聚簇索引。InnoDB只聚集在同一個(gè)頁面中的記錄,包括相鄰鍵值的頁面可能會(huì)相距甚遠(yuǎn)。

(看到這里,如果你對(duì)B-Tree索引結(jié)構(gòu)熟悉的話,就知道為啥[key、data]作為一個(gè)二元組存放在一個(gè)節(jié)點(diǎn)了)

聚簇主鍵可能對(duì)性能有幫助,但也可能導(dǎo)致嚴(yán)重的性能問題。所以需要仔細(xì)的考慮聚簇索引,尤其是將表的存儲(chǔ)引擎從InnoDB改成其他引擎的時(shí)候(反過來也一樣)。

聚簇索引的優(yōu)點(diǎn):

  • 可以把相關(guān)數(shù)據(jù)保存在一起。例如實(shí)現(xiàn)電子郵箱時(shí),可以根據(jù)用戶ID來聚集數(shù)據(jù),這樣子只需要從磁盤中讀取少數(shù)的數(shù)據(jù)也技能獲取某個(gè)用戶的全部郵件。
  • 數(shù)據(jù)訪問更快。聚簇索引把索引和數(shù)據(jù)都放在同一個(gè)B-Tree中,因此從聚簇索引中獲取數(shù)據(jù)比從非聚簇索引中要快。
  • 使用覆蓋索引掃描的查詢可以直接使用頁節(jié)點(diǎn)中的主鍵值。
     

聚簇索引的缺點(diǎn):

  • 最大限度的提高了I/O密集型應(yīng)用的性能,但如果數(shù)據(jù)全部都放在內(nèi)存中,則訪問的順序就沒那么重要了,聚簇索引也就沒什么優(yōu)勢(shì)了。
  • 插入速度嚴(yán)重依賴于插入順序。按照主鍵的順序插入是加載數(shù)據(jù)到InnoDB表中速度最快的方式。但如果不是按照逐漸順序加載數(shù)據(jù),那么在加載完成后最好使用OPTIMIZE TABLE重新組織一下表。
  • 更新聚簇索引列的代價(jià)很高。因?yàn)橐獜?qiáng)制InnoDB將每個(gè)被更新的行移動(dòng)到新的位置。
  • 基于聚簇索引的表在插入新行,或者主鍵被更新導(dǎo)致移動(dòng)行的時(shí)候,可能面臨“頁分裂”的問題。當(dāng)行的主鍵值要求必須將這一行插入到某個(gè)已滿的頁中時(shí),存儲(chǔ)引擎會(huì)將該頁分裂成兩個(gè)頁來容納該行,這就是一次頁分裂操作,這也意味著這樣導(dǎo)致表占用更多的磁盤空間。
  • 聚簇索引可能導(dǎo)致全表掃描變慢,尤其是行比較稀疏時(shí),或者由于頁分裂導(dǎo)致數(shù)據(jù)存儲(chǔ)不連續(xù)的時(shí)候。
  • 二級(jí)索引(非聚簇索引)可能比想想的要更大。因?yàn)槎?jí)索引的葉子結(jié)點(diǎn)包含了引用行的主鍵列。
  • 二級(jí)索引訪問需要兩次索引查找,而不是一次。
     

六、覆蓋索引

通常大家都會(huì)根據(jù)查詢的where條件來創(chuàng)建合適的索引,不過這也只是索引優(yōu)化的一個(gè)方面。設(shè)計(jì)優(yōu)秀的索引應(yīng)該考慮到整個(gè)查詢,而不單單是where條件部分。索引確實(shí)是一種查找數(shù)據(jù)的高效方式,但是MySQL也可以使用索引來直接獲取列的數(shù)據(jù),這樣就不再需要讀取數(shù)據(jù)行。如果一個(gè)索引包含所有需要查詢的字段值,我們就稱其為“覆蓋索引”,即:一個(gè)索引覆蓋where條件的所有列。

覆蓋索引的好處如下:

  • 索引條目通常遠(yuǎn)小于數(shù)據(jù)行的大小,所以如果只需要讀取索引,那么MySQL就會(huì)極大的減少數(shù)據(jù)訪問量。這對(duì)緩存的負(fù)載非常重要,因?yàn)檫@種情況下響應(yīng)時(shí)間大部分花費(fèi)在數(shù)據(jù)拷貝下。覆蓋索引對(duì)于I/O密集型的應(yīng)用也有幫助,因?yàn)樗饕葦?shù)據(jù)更小,更容易全部放進(jìn)去內(nèi)存。
  • 因?yàn)樗饕前凑樟兄淀樞虼鎯?chǔ)的,對(duì)于I/O密集型的范圍查詢會(huì)比隨機(jī)從磁盤讀取每一行數(shù)據(jù)的I/O要少的多。對(duì)于某些存儲(chǔ)引擎,例如MyISAMPercona XtraDB,甚至可以通過POTIMIZE命令使得索引完全順序排列,這樣就可以讓簡(jiǎn)單的范圍查詢能使用完全排序的索引訪問。
  • 一些存儲(chǔ)引擎,如MyISAM在內(nèi)存中只緩存索引。數(shù)據(jù)則依賴于操作系統(tǒng)來緩存,因此要訪問數(shù)據(jù)需要一次系統(tǒng)調(diào)用。這可能會(huì)導(dǎo)致嚴(yán)重的性能問題,尤其是那些系統(tǒng)調(diào)用占了數(shù)據(jù)訪問中的最大開銷的場(chǎng)景。
  • 由于InnoDB的聚簇索引,覆蓋索引對(duì)于InnoDB表特別有用。InnoDB的二級(jí)索引在葉子節(jié)點(diǎn)保存了行的主鍵值,所以如果二級(jí)主鍵能夠覆蓋查詢,則可以避免對(duì)主鍵索引的二次查詢
     

不是所有類型的索引都可以成為覆蓋索引。覆蓋索引必須要存儲(chǔ)索引列,而哈希索引、空間索引和全文索引等都不存儲(chǔ)索引列的值,所以MySQL只能使用B-Tree所以來做覆蓋索引,另外不同的存儲(chǔ)引擎實(shí)現(xiàn)覆蓋索引的方式也不同,而且不是所有的引擎都支持覆蓋索引。

七、使用索引掃描來排序

MySQL有兩種方式可以生成有序的結(jié)果集:通過排序操作,或者按索引順序掃描。如果EXPLAIN出來的type列的值為index,則說明MySQL使用了索引掃描來做排序。

掃描索引本身是很快的,因?yàn)橹恍枰獜囊粭l索引記錄移動(dòng)到緊接著的下一條記錄。但如果索引不能覆蓋查詢所需的全部列,那就不得不每掃描一條索引記錄就都回表查詢一次對(duì)應(yīng)的行。這基本上都是隨機(jī)I/O,因此按索引順序讀取數(shù)據(jù)的速度通常要比順序的全表掃描慢,尤其是在I/O密集型的工作負(fù)載時(shí)。

MySQL可以使用同一個(gè)索引既滿足排序,又用于查找行。因此,如果可能,設(shè)計(jì)索引時(shí)應(yīng)該盡可能的同時(shí)滿足這兩種情況,即:索引列作為排序列。

  • 只有當(dāng)索引的列順序和order by子句的順序完全一致,并且所有列的排序方向都一樣時(shí),MySQL才能夠使用索引來對(duì)結(jié)果做排序。
  • 如果查詢需要關(guān)聯(lián)多張表,則只有當(dāng)order by子句引用的字段全部為第一個(gè)表時(shí),才能使用索引做排序。order by子句和查找性查詢的限制是一樣的:需要滿足索引的最左前綴的要求;否則,MySQL都需要執(zhí)行的順序操作,而無法使用索引排序。
     

八、冗余、重復(fù)索引

重復(fù)索引,是指在相同列上按照相同的順序創(chuàng)建的相同類型的索引。應(yīng)該避免這樣的創(chuàng)建重復(fù)索引,發(fā)現(xiàn)以后也應(yīng)該立即移除。

比如:   

create table test{
 id int not null primary key,
 a int not null,
 b int not null,
 unique(id)
 index(id)
}engine=InnoDB;

一個(gè)經(jīng)驗(yàn)不足的人可能是想創(chuàng)建一個(gè)主鍵,先加上唯一限制(unique(id)),然后再加上索引(index(id))以供查詢使用。然而唯一限制和主鍵限制都是通過索引使用,因此,上面的寫法實(shí)際上在相同的列上創(chuàng)建了三個(gè)重復(fù)的索引。通常并沒有理由要這樣做,除非是在同一列上創(chuàng)建不同類型的索引來滿足不同的查詢需求。

冗余索引和重復(fù)索引有一些不同,比如:如果創(chuàng)建了索引(A,B),再創(chuàng)建(A)那就是冗余索引,因?yàn)锳就是前一個(gè)索引的前綴索引。索引(A,B)完全就可以當(dāng)做A來使用。但是如果創(chuàng)建了索引(B,A)那就不是冗余索引了,索引B也不是。因?yàn)锽不是索引(A,B)的最左前綴索引。另外,其他不同類型的索引,例如哈希,全文索引也不會(huì)是B-Tree的冗余索引。

冗余索引通常發(fā)生在為表添加新索引的時(shí)候。例如,有人可能會(huì)增加一個(gè)新的索引(A,B)而不是拓展已有的索引(A),還有一種情況是將一個(gè)索引擴(kuò)展為(A,ID),其中的ID是主鍵,對(duì)于InnoDB來說主鍵列已經(jīng)包含在二級(jí)索引當(dāng)中了, 所以這也是冗余的。

大多數(shù)情況下不需要冗余索引,應(yīng)該盡量擴(kuò)展已有的索引而不是創(chuàng)建新的索引。但也有時(shí)候處于性能方面的考慮需要冗余索引,因?yàn)閿U(kuò)展已有的索引會(huì)導(dǎo)致其變得太大 ,從而影響其他使用該索引的查詢的性能。例如,在一個(gè)整數(shù)列索引上添加一個(gè)很長(zhǎng)的varchar列,那性能可能會(huì)急劇下降。特別是有索引把這個(gè)索引當(dāng)中覆蓋索引時(shí),或者這是MyISAM表并且有很多范圍查詢的時(shí)候。

解決冗余索引和重復(fù)索引的方法非常簡(jiǎn)單,刪除這些索引就可以。但是首先要做的事找出這樣的索引??梢酝ㄟ^寫一些復(fù)雜的訪問information_schema表的查詢來找,不過還有兩個(gè)更簡(jiǎn)單的方法就是使用Shlomi Noachcommon_schema中的一些視圖來定位(common_schema是一系列可以安裝在服務(wù)器上的常用的存儲(chǔ)和視圖)。另外一個(gè)方法就是使用Percona Toolkit中的pt_duplicate-key-checker,該工具通過分析表結(jié)構(gòu)來找出冗余和重復(fù)索引。

九、未使用的索引

除了冗余索引和重復(fù)索引,可能還會(huì)有一些服務(wù)器永遠(yuǎn)不用的索引。這樣的索引完全是累贅,建議直接刪除。

可以使用Performance_schema中的table_io_waits_summary_by_index_usage表進(jìn)行查找:

SELECT object_schema, object_name, index_name FROM performance_schema.table_io_waits_summary_by_index_usage WHERE index_name IS NOT NULL AND count_star = 0 ORDER BY object_schema, object_name, index_name;

十、索引和鎖

索引可以讓查詢鎖定更少的行。如果你的查詢從不訪問那些不需要的行,那么就會(huì)鎖定更少的行,從兩個(gè)方面來看這對(duì)性能都有什么好處。

首先,雖然InnoDB的行鎖效率很高,內(nèi)存使用也很少,但是鎖定行的時(shí)候仍然會(huì)帶來額外的開銷,其次,鎖定超過需要的行會(huì)增加鎖爭(zhēng)用并減少并發(fā)性。

十一、總結(jié)

通過上面大篇文字的講解,都是用來說明如何高效的使用索引,避免錯(cuò)誤使用。索引是一個(gè)看似簡(jiǎn)單,但實(shí)際用起來卻是非常復(fù)雜的東西,要想真正用好它,需要不斷的實(shí)踐。實(shí)踐是檢驗(yàn)真理的唯一途徑,本篇只是站在索引使用的全局來定位的,你只需要通讀全篇并結(jié)合具體的例子,或回憶以往使用過的地方,對(duì)整體有個(gè)全面認(rèn)識(shí),并理解索引是如何工作的,就可以了。在后續(xù)使用索引,或者優(yōu)化索引時(shí),可以從這些方面出發(fā),進(jìn)一步來加深對(duì)索引正確高效的使用。

在平時(shí)使用索引中,有以下幾點(diǎn)總結(jié)及建議:

  1. 在區(qū)分度高的字段上面建立索引可以有效的使用索引,區(qū)分度太低,無法有效的利用索引,可能需要掃描所有數(shù)據(jù)頁,此時(shí)和不使用索引區(qū)別不大。
  2. 聯(lián)合索引,注意最左匹配原則:必須按照從左到右的順序匹配,MySQL會(huì)一直向右匹配直到遇到范圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調(diào)整。
  3. 查詢記錄的時(shí)候,少使用*,盡量去利用索引覆蓋,可以減少回表操作,提升效率。
  4. 有些查詢可以采用聯(lián)合索引,進(jìn)而使用到索引下推,也可以減少回表操作,提升效率。
  5. 禁止對(duì)索引字段使用函數(shù)、運(yùn)算符操作,這樣將會(huì)使索引失效。
  6. 字符串字段和數(shù)字比較的時(shí)候會(huì)使索引無效。
  7. 模糊查詢 '%值%' 會(huì)使索引無效,變?yōu)槿頀呙?,但?code> '值%' 這種可以有效利用索引。
  8. 排序中盡量使用到索引字段,這樣可以減少排序,提升查詢效率。

關(guān)于MySQL中高效正確使用索引的方法就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI