高性能索引

MySQL 官方對索引(Index)的定義是存儲引擎用于快速查找記錄的一種數(shù)據(jù)結(jié)構(gòu)。
(1)索引是物理數(shù)據(jù)頁,數(shù)據(jù)庫頁大?。≒age Size)決定了一個頁可以存儲多少個索引行,以及需要多少頁來存儲指定大小的索引。
(2)索引可以加快檢索速度,但同時也降低索引列插入、刪除、更新的速度,索引維護(hù)需要代價。

索引涉及的理論知識有二分查找法、哈希表及 B+Tree。

二分查找法
二分查找法也叫作折半查找法,它是在有序數(shù)組中查找指定數(shù)據(jù)的搜索算法它的優(yōu)點是等值查詢、范圍查詢性能優(yōu)秀,缺點是更新數(shù)據(jù)、新增數(shù)據(jù)、刪除數(shù)據(jù)維護(hù)成本高。

一、索引原理

1.hash索引

哈希表是數(shù)據(jù)庫中哈希索引的基礎(chǔ),是根據(jù)鍵值 ?key,value? 存儲數(shù)據(jù)的結(jié)構(gòu)。簡單說,哈希表是使用哈希函數(shù)將索引列計算到桶或槽的數(shù)組,實際存儲是根據(jù)哈希函數(shù)將 key 換算成確定的存儲位置,并將 value 存放到該數(shù)組位置上。訪問時,只需要輸入待查找的 key,即可通過哈希函數(shù)計算得出確定的存儲位置并讀取數(shù)據(jù)。

如下圖所示,姓名作為 key,通過哈希函數(shù)對姓名字段數(shù)據(jù)進(jìn)行計算,得到哈希碼并存放到桶或槽的數(shù)組中,同時存放指向真實數(shù)據(jù)行的指針作為 value,形成哈希表。

image

如下圖所示,根據(jù)表中的 name 字段構(gòu)建 Hash 索引,通過 Hash 算法對每一行 name 字段的數(shù)據(jù)進(jìn)行計算,得出 Hash 碼。由 Hash 碼及 Hash 碼指向真實數(shù)據(jù)行的指針組成了哈希索引。

image

因為哈希索引只存儲哈希值和行指針,不存儲實際字段值,所以其結(jié)構(gòu)緊湊,查詢速度也非常快,在無哈希沖突的場景下訪問哈希索引一次即可命中。但是哈希索引只適用于等值查詢,包括 =、IN()、?=? (安全等于, select null ?=? null 和 select null=null 是不一樣的結(jié)果) ,不支持范圍查詢。

(1)Hash 碰撞
Hash 碰撞是指不同索引列值計算出相同的哈希碼,如上圖所示, 表中 name 字段為 John Smith 和 Sandra Dee 兩個不同值根據(jù) Hash 算法計算出來的哈希碼都是 152,這就表示出現(xiàn)了 Hash 碰撞。 對于 Hash 碰撞通用的處理方法是使用鏈表,將 Hash 沖突碰撞的元素形成一個鏈表,發(fā)生沖突時在鏈表上進(jìn)行二次遍歷找到數(shù)據(jù)。

綜合建議 Hash 算法使用優(yōu)先級為:FNV64 ? CRC32 (大數(shù)據(jù)量下 Hash 沖突概率較大)? MD5 ? SHA1。

2.MySQL 中如何使用 Hash 索引?

在 MySQL 中主要是分為 Memory 存儲引擎原生支持的 Hash 索引 、InnoDB 自適應(yīng)哈希索引及 NDB 集群的哈希索引3類。
(1)Memory 存儲引擎原生支持的 Hash 索引,Memory 存儲引擎創(chuàng)建表時即可原生顯式創(chuàng)建并使用 Hash 索引。
(2)InnoDB 自適應(yīng)哈希索引是為了提升查詢效率,InnoDB 存儲引擎會監(jiān)控表上各個索引頁的查詢,當(dāng) InnoDB 注意到某些索引值訪問非常頻繁時,會在內(nèi)存中基于 B+Tree 索引再創(chuàng)建一個哈希索引,使得內(nèi)存中的 B+Tree 索引具備哈希索引的功能,即能夠快速定值訪問頻繁訪問的索引頁。

為什么要為 B+Tree 索引頁二次創(chuàng)建自適應(yīng)哈希索引呢
這是因為 B+Tree 索引的查詢效率取決于 B+Tree 的高度,在數(shù)據(jù)庫系統(tǒng)中通常 B+Tree 的高度為 3~4 層,所以訪問數(shù)據(jù)需要做 3~4 次的查詢。而 Hash 索引訪問通常一次查找就能定位數(shù)據(jù)(無 Hash 碰撞的情況),其等值查詢場景 Hash 索引的查詢效率要優(yōu)于 B+Tree。

自適應(yīng)哈希索引的建立使得 InnoDB 存儲引擎能自動根據(jù)索引頁訪問的頻率和模式自動地為某些熱點頁建立哈希索引來加速訪問。另外 InnoDB 自適應(yīng)哈希索引的功能,用戶只能選擇開啟或關(guān)閉功能,無法進(jìn)行人工干涉。

功能開啟后可以通過 Show Engine Innodb Status 看到當(dāng)前自適應(yīng)哈希索引的使用情況:
Hash table size 276707, node heap has 0 buffer(s)
0.00 Hash searches/s, 0.00 non-Hash searches/s

二、B+Tree 索引

在 MySQL 數(shù)據(jù)庫中討論索引時,如果沒有明確指定類型,則默認(rèn)是指使用 B+Tree 數(shù)據(jù)結(jié)構(gòu)進(jìn)行存儲,其說法等價于 B+Tree、B-Tree、BTREE(看到創(chuàng)建索引語句為 BTREE 也不要驚訝,等同于 B+Tree)。

如下圖所示為一個簡單的、標(biāo)準(zhǔn)的 B+tree,每個節(jié)點有 K 個鍵值和 K+1 個指針。

image

對于 MySQL 存儲引擎而言,其實際使用的 B+Tree 索引是為了滿足數(shù)據(jù)讀寫性能,以及適配磁盤訪問模式優(yōu)化后的數(shù)據(jù)結(jié)構(gòu),每一個葉子節(jié)點都包含指向下一個葉子節(jié)點的指針。

在 MySQL 中,索引是在存儲引擎層而非服務(wù)器層實現(xiàn)的,所以不同存儲引擎層支持的索引類型可以不同。例如,雖然 MyISAM 和 InnoDB 的索引都是使用 B+Tree 實現(xiàn)的,但是其實際數(shù)據(jù)存儲結(jié)構(gòu)有不少差異。下圖中 B+Tree 示例一共2層,圖中每個頁面都已經(jīng)被隨機(jī)編號(編號可以認(rèn)定為頁面號),其中頁面號為 20 的頁面是 B+Tree 的根頁面(根頁面通常是存放在內(nèi)存中的),根頁面存儲了 ?key+pageno?,pageno 是指向具體葉子節(jié)點的頁面號。其他頁面都是葉子節(jié)點,存放了具體的數(shù)據(jù) ?key+data?。


image.png

B+Tree 索引能夠快速訪問數(shù)據(jù),就是因為存儲引擎可以不再需要通過全表掃描來獲取數(shù)據(jù),而是從索引的根結(jié)點(通常在內(nèi)存中)開始進(jìn)行二分查找,根節(jié)點的槽中都存放了指向子節(jié)點的指針,存儲引擎根據(jù)這些指針能夠快速遍歷數(shù)據(jù)。例如,通過頁面號為 20 的根節(jié)點可以快速得知 Key?10 的數(shù)據(jù)在 pageno 33 的頁面,key在 [10,16) 范圍的數(shù)據(jù)在 pageno 56 的頁面。

葉子節(jié)點存放的 ?key+data? ,對于真正要存放哪些數(shù)據(jù)還得取決于該 B+Tree 是聚簇索引(Clustered Index)還是輔助索引(Secondary Index)。

1.聚簇索引

聚簇索引是一種數(shù)據(jù)存儲方式,它表示表中的數(shù)據(jù)按照主鍵順序存儲,是索引組織表。InnoDB 的聚簇索引就是按照主鍵順序構(gòu)建 B+Tree,B+Tree 的葉子節(jié)點就是行記錄,數(shù)據(jù)行和主鍵值緊湊地存儲在一起。 這也意味著 InnoDB 的主鍵索引就是數(shù)據(jù)表本身,它按主鍵順序存放了整張表的數(shù)據(jù)。

2. 輔助索引

輔助索引(也叫作二級索引)只是根據(jù)索引列構(gòu)建 B+Tree,但在 B+Tree 的每一行都存了主鍵信息,加速回表操作。

區(qū)別:
(1)聚簇索引占用的空間就是整個表數(shù)據(jù)量的大小,而二級索引會比聚簇索引小很多, 通常創(chuàng)建輔助索引就是為了提升查詢效率。
(2)InnoDB 只能創(chuàng)建一個聚簇索引(假想下如果能支持多個聚簇索引,那就意味著一張表按不同排序規(guī)則冗余存儲多份全表數(shù)據(jù)了),但可以創(chuàng)建多個輔助索引。

擴(kuò)展:
相比索引組織表,還有一種堆表類型,堆表是根據(jù)數(shù)據(jù)寫入的順序直接存儲在磁盤上的。對于堆表而言,其主鍵和輔助索引唯一的區(qū)別就是鍵值是否唯一,兩者都是根據(jù)索引列排序構(gòu)建 B+Tree 的,在每個葉子節(jié)點加上指向堆表的行指針(row data pointer) 。堆表在各類數(shù)據(jù)庫中也被廣泛使用,MyISAM 存儲引擎的表就是堆表。

三、 索引類型

MySQL 中索引是在存儲引擎層而非服務(wù)器層實現(xiàn)的,所以不同存儲引擎層支持的索引類型可以不同。

在 MySQL 中不同存儲引擎間支持的常見索引類型有:哈希索引(Memory/InnoDB adaptive Hash index/NDB)、 B+Tree 索引(MyISAM/InnoDB)、全文索引(MyISAM/InnoDB)、空間索引(MyISAM R-Tree)、分形樹索引(TokuDB Fractal Tree Index),如下表所示。


image

在 MySQL InnoDB 中索引通??梢苑譃閮纱箢悾褐麈I索引(即聚簇索引)和輔助索引(非聚簇索引) 。

對于沒有指定主鍵的表,InnoDB 會自己選擇合適字段為主鍵,其選擇順序如下:
(1)顯式主鍵;
(2)第一個唯一索引(要求唯一索引所有列都非 NULL);
(3)內(nèi)置的 6 字節(jié) ROWID。

根據(jù)索引列個數(shù)和功能描述不同索引也可以分為:聯(lián)合索引和覆蓋索引。
(1)聯(lián)合索引是指在多個字段聯(lián)合組建索引的。
(2)當(dāng)通過索引即可查詢到所有記錄,不需要回表到聚簇索引時,這類索引也叫作覆蓋索引。
(3)主鍵查詢是天然的覆蓋索引,聯(lián)合索引可以是覆蓋索引。

通常在查看執(zhí)行計劃時, Extra 列為 Using index 則表示優(yōu)化器使用了覆蓋索引。

我們通常建議優(yōu)先考慮使用覆蓋索引,這是因為如果 SQL 需要查詢輔助索引中不包含的數(shù)據(jù)列時,就需要先通過輔助索引查找到主鍵值,然后再回表通過主鍵查詢到其他數(shù)據(jù)列(即回表查詢),需要查詢兩次。而覆蓋索引能從索引中直接獲取查詢需要的所有數(shù)據(jù),從?避免回表進(jìn)行二次查找,節(jié)省IO,效率較?。

例如,SELECT email,uid FROM user_email WHERE uid=xx,如果 uid 不是主鍵,那可以將索引添加為 index(uid,email),以獲得查詢性能提升。

四、索引使用技巧

1.謂詞

謂詞本身就是條件表達(dá)式,通俗講就是過濾字段。如下圖中這句SQL語句,可以拆解為下面所示:

image

(1)簡單謂詞:city和 last_updata。
(2)組合謂詞:city and last_updata。

2.過濾因子

滿足謂詞條件的記錄行數(shù)除以表總行數(shù)。
(1)簡單謂詞的過濾因子 = 謂詞結(jié)果集的數(shù)量 / 表總行數(shù)
(2)組合謂詞的過濾因子 = 謂詞 1 的過濾因子 × 謂詞 2 的過濾因子

注意:過濾因子直接描述了謂詞的選擇性,表示滿足謂詞條件的記錄行數(shù)所占比例,過濾因子越小意味著能過濾越多數(shù)據(jù),你需要在這類謂詞字段上創(chuàng)建索引。

3.基數(shù)(Cardinality)

基數(shù)是某個鍵值去重后的行數(shù), 索引列不重復(fù)記錄數(shù)量的預(yù)估值,MySQL 優(yōu)化器會依賴于它。

Cardinality 能快速告知字段的選擇性,高選擇性字段有利于創(chuàng)建索引。優(yōu)化器在選擇執(zhí)行計劃時會依賴該信息,通常這類信息也叫作統(tǒng)計信息,數(shù)據(jù)庫中對于統(tǒng)計信息的采集是在存儲引擎層進(jìn)行的。

執(zhí)行 show index from table_name 會看到 Cardinality,同時也會觸發(fā) MySQL 數(shù)據(jù)庫對 Cardinaltiy 值的統(tǒng)計。除此之外,還有三種更新策略。(1)觸發(fā)統(tǒng)計:Cardinality 統(tǒng)計信息更新發(fā)生在 INSERT 和 UPDATE 時,InnoDB 存儲引擎內(nèi)部更新的 Cardinality 信息的策略為:
表中超過1/16的數(shù)據(jù)發(fā)生變化;
stat_modified_counter ? 2000 000 000 (20億)。
(2)采樣統(tǒng)計(sample):為了減少統(tǒng)計信息更新造成的資源消耗,數(shù)據(jù)庫對Cardinality 通過采樣來完成統(tǒng)計信息更新,每次隨機(jī)獲取 innodb_stats_persistent_sample_pages 頁的數(shù)量進(jìn)行 Cardinality 統(tǒng)計。
(3)手動統(tǒng)計:alter table table_name engine=innodb 或 analyze table table_name,當(dāng)發(fā)現(xiàn)優(yōu)化器選擇錯誤的執(zhí)行計劃或沒有走理想的索引時,執(zhí)行 SQL 語句來手動統(tǒng)計信息有時是一種有效的方法。

由于采樣統(tǒng)計的信息是隨機(jī)獲取8個(8是由innodb_stats_transient_sample_pages參數(shù)指定)頁面數(shù)進(jìn)行分析,這就意味著下一次隨機(jī)的 8 個頁面可能是其他頁面,其采集頁面的 Carinality 也不同。因此當(dāng)表數(shù)據(jù)無變化時也會出現(xiàn) Cardinality 發(fā)生變化的情況,如下圖所示。

image

關(guān)于統(tǒng)計信息的采集涉及如下主要參數(shù)。
(1)information_schema_stats_expiry:86400,Cardinality 存放過期時間,設(shè)置為 0 表示實時獲取統(tǒng)計信息,嚴(yán)重影響性能,建議設(shè)置默認(rèn)值并通過手動刷新統(tǒng)計信息;
(2)innodb_stats_auto_recalc:ON,是否自動更新統(tǒng)計信息,默認(rèn)即可;
(3)innodb_stats_include_delete_marked :OFF,計算持久化統(tǒng)計信息時 InnoDB 是否包含 Delete-marked 記錄,默認(rèn)即可;
(4)innodb_stats_method:nulls_equal,用來判斷如何對待索引中出現(xiàn)的 NULL 值記錄,默認(rèn)為 nulls_equal,表示將 NULL 值記錄視為相等的記錄;
(5)innodb_stats_on_metadata, 默認(rèn)值 OFF,執(zhí)行 SQL 語句 ANALYZE TABLE、SHOW TABLE STATUS、SHOQ INDEX,以及訪問 INFORMATION_SCHEMA 架構(gòu)下表 tables和statistics 時,是否重新計算索引的 Cardinality 值;
(6)innodb_stats_persistent:ON,表示通過 ANALYZE TABLE 計算得到的 Cardinality值存放到磁盤上;
(7)innodb_stats_persistent_sample_pages:20,表示 ANALYZE TABLE 更新Cardinality 值時采樣頁的數(shù)量;
(8)innodb_stats_transient_sample_pages:8,表示每次統(tǒng)計 Cardinality 時采樣頁的數(shù)量,默認(rèn)為 8。

4.選擇率

選擇率是 count(distinct city) / count(*),選擇率越接近 1 則越適合創(chuàng)建索引,例如主鍵和唯一鍵的選擇率都是 1?;乇硎侵笩o法通過索引掃描訪問所有數(shù)據(jù),需要回到主表進(jìn)行數(shù)據(jù)掃描并返回。

五、

1.索引使用細(xì)節(jié)

執(zhí)行計劃重點關(guān)注跟索引相關(guān)的關(guān)鍵項,有 type、possible_keys、key、key_len、ref、Extra 等。

其中,possible_keys 表示查詢可能使用的索引,key表示真正實際使用的索引,key_len 表示使用索引字段的長度。

另外執(zhí)行計劃中 Extra 選項也值得關(guān)注,例如 Extra 顯示 use index 時就表示該索引是覆蓋索引,通常性能排序的結(jié)果是 usd index ? use where ? use filsort,如下圖所示。

image

當(dāng)索引選擇組合索引時,通過計算 key_len 來了解有效索引長度對索引優(yōu)化也是非常重要的,接下來重點講解 key_len 計算規(guī)則。

key_len 表示得到結(jié)果集所使用的選擇索引的長度[字節(jié)數(shù)],不包括 order by,也就是說如果 order by 也使用了索引則 key_len 不計算在內(nèi)。

key_len 計算規(guī)則從兩個方面考慮,一方面是索引字段的數(shù)據(jù)類型,另一方面是表、字段所使用的字符集。

  1. 索引字段的數(shù)據(jù)類型,根據(jù)索引字段的定義可以分為變長和定長兩種數(shù)據(jù)類型:
    索引字段為定長數(shù)據(jù)類型,比如 char、int、datetime,需要有是否為空的標(biāo)記,這個標(biāo)記需要占用 1 個字節(jié);
    對于變長數(shù)據(jù)類型,比如 Varchar,除了是否為空的標(biāo)記外,還需要有長度信息,需要占用 2 個字節(jié);(備注:當(dāng)字段定義為非空的時候,是否為空的標(biāo)記將不占用字節(jié))。

2)表所使用的字符集,不同的字符集計算的 key_len 不一樣,例如,GBK 編碼的是一個占用 2 個字節(jié)大小的字符,UTF8 編碼的是一個占用 3 個字節(jié)大小的字符。
舉例說明:在四類字段上創(chuàng)建索引后的 key_len 如何計算呢?
(1) Varchr(10) 變長字段且允許 NULL:10(Character Set:utf8=3,gbk=2,latin1=1)+1(標(biāo)記是否為 NULL 需要 1 個字節(jié))+ 2(變長字段存儲長度信息需要 2 個字節(jié))。
(2) Varchr(10) 變長字段且不允許 NULL:10
(Character Set:utf8=3,gbk=2,latin1=1)+2(變長字段存儲長度信息需要2個字節(jié)),非空不再需要占用字節(jié)來標(biāo)記是否為空。
(3) Char(10) 固定字段且允許 NULL:10(Character Set:utf8=3,gbk=2,latin1=1)+1(標(biāo)記是否為 NULL 需要 1 個字節(jié))。
(4) Char(10) 固定字段且不允許 NULL:10
(Character Set:utf8=3,gbk=2,latin1=1),非空不再需要占用字節(jié)來標(biāo)記是否為空。

2.最左前綴匹配原則

通過 key_len 計算也幫助我們了解索引的最左前綴匹配原則。

最左前綴匹配原則是指在使用 B+Tree 聯(lián)合索引進(jìn)行數(shù)據(jù)檢索時,MySQL 優(yōu)化器會讀取謂詞(過濾條件)并按照聯(lián)合索引字段創(chuàng)建順序一直向右匹配直到遇到范圍查詢或非等值查詢后停止匹配,此字段之后的索引列不會被使用,這時計算 key_len 可以分析出聯(lián)合索引實際使用了哪些索引列。

3.設(shè)計性能索引

image

創(chuàng)建一個 test 表。 在 a、b、c 上創(chuàng)建索引,執(zhí)行表中的 SQL 語句,快速定位語句孰好孰壞。

首先分析 key_len, 因為 a、b、c 不允許 NULL 的 varchar(50),那么,每個字段的 key_len 為 50×4+2=202,整個聯(lián)合索引的 key_len 為 202×3=606

image

(1) SQL1 可以使用覆蓋索引,性能好;
(2)SQL2 可以使用覆蓋索引同時可以避免排序,性能好;
(3)SQL3 可以使用覆蓋索引,但是需要根據(jù) where 字句進(jìn)行過濾;
(4)SQL4 可以使用部分索引 a,但無法避免排序,性能差;
(5)SQL5 完全使用覆蓋索引,同時可以避免排序,性能好;
(6)SQL6 可以使用覆蓋索引,但無法避免排序,這是因為 MySQL InnoDB 創(chuàng)建索引時默認(rèn)asc升序,索引無法自動倒序排序;
(7)SQL7 可以使用覆蓋索引,但是需要根據(jù) where 子句進(jìn)行過濾(非定值查詢)。
在實際設(shè)計高性能索引時,可以結(jié)合前面講解的內(nèi)容按照如下步驟進(jìn)行分析。
(1)定位由于索引不合適或缺少索引而導(dǎo)致的慢查詢。
通常在業(yè)務(wù)建庫建表時就需要提交業(yè)務(wù)運(yùn)行相關(guān)的 SQL 給 DBA 審核,也可以借助Arkcontrol Arkit 來自動化審核。比如,慢查詢?nèi)罩痉治?,抓出運(yùn)行慢的 SQL 進(jìn)行分析,也可以借助第三方工具例如 Arkcontrol 慢查詢分析系統(tǒng)進(jìn)行慢查詢采集和分析。在分析慢查詢時進(jìn)行參數(shù)最差輸入,同時,對 SQL 語句的謂詞進(jìn)行過濾因子、基數(shù)、選擇率和 SQL 查詢回表情況的分析。
(2)設(shè)計索引。
設(shè)計索引的目標(biāo)是讓查詢語句運(yùn)行得足夠快,同時讓表、索引維護(hù)也足夠快,例如,使用業(yè)務(wù)不相關(guān)自增字段為主鍵,減緩頁分裂、頁合并等索引維護(hù)成本,加速性能。也可以使用第三方工具進(jìn)行索引設(shè)計,例如 Arkcontrol SQL 優(yōu)化助手,會給出設(shè)計索引的建議。
(3)創(chuàng)建索引策略。
優(yōu)先為搜索列、排序列、分組列創(chuàng)建索引,必要時加入查詢列創(chuàng)建覆蓋索引;計算字段列基數(shù)和選擇率,選擇率越接近于 1 越適合創(chuàng)建索引;索引選用較小的數(shù)據(jù)類型(整型優(yōu)于字符型),字符串可以考慮前綴索引;不要建立過多索引,優(yōu)先基于現(xiàn)有索引調(diào)整順序;參與比較的字段類型保持匹配并創(chuàng)建索引。
(4)調(diào)優(yōu)索引。
分析執(zhí)行計劃;更新統(tǒng)計信息(Analyze Table);Hint優(yōu)化,方便調(diào)優(yōu)(FORCE INDEX、USE INDEX、IGNORE INDEX、STRAIGHT_JOIN);檢查連接字段數(shù)據(jù)類型、字符集;避免使用類型轉(zhuǎn)換;關(guān)注 optimizer_switch,重點關(guān)注索引優(yōu)化特性 MRR(Multi-Range Read)和 ICP(Index Condition Pushdown)。
1)MRR 優(yōu)化是為了減少磁盤隨機(jī)訪問,將隨機(jī) IO 轉(zhuǎn)化為順序 IO 的數(shù)據(jù)訪問,其方式是將查詢得到輔助索引的鍵值放到內(nèi)存中進(jìn)行排序,通常是按照主鍵或 RowID 進(jìn)行排序,當(dāng)需要回表時直接根據(jù)主鍵或 RowID 排序順序訪問實際的數(shù)據(jù)文件,加速 SQL 查詢。
2)ICP 優(yōu)化同樣也是對索引查詢的優(yōu)化特性,MySQL 根據(jù)索引查詢到數(shù)據(jù)后會優(yōu)先應(yīng)用 where 條件進(jìn)行數(shù)據(jù)過濾,即無法使用索引過濾的 where 子句,其過濾由之前 Server 層的數(shù)據(jù)過濾下推到了存儲引擎層,可以減少上層對記錄的檢索,提高數(shù)據(jù)庫的整體性能。

4.創(chuàng)建索引規(guī)范

(1)命名規(guī)范, 各個公司內(nèi)部統(tǒng)一。
(2)考慮到索引維護(hù)的成本,單張表的索引數(shù)量不超過 5 個,單個索引中的字段數(shù)不超過 5 個。
(3)表必需有主鍵,推薦使? UNSIGNED 自增列作為主鍵。表不設(shè)置主鍵時 InnoDB 會默認(rèn)設(shè)置隱藏的主鍵列,不便于表定位數(shù)據(jù)同時也會增大 MySQL 運(yùn)維成本(例如主從復(fù)制效率嚴(yán)重受損、pt 工具無法使用或正確使用)。
(4)唯一鍵由 3 個以下字段組成,并且在字段都是整形時,可使用唯一鍵作為主鍵。其他情況下,建議使用自增列或發(fā)號器作主鍵。
(5)禁止冗余索引、禁止重復(fù)索引,索引維護(hù)需要成本,新增索引時優(yōu)先考慮基于現(xiàn)有索引進(jìn)行 rebuild,例如 (a,b,c)和 (a,b),后者為冗余索引可以考慮刪除。重復(fù)索引也是如此,例如索引(a)和索引(a,主鍵ID) 兩者重復(fù),增加運(yùn)維成本并占用磁盤空間,按需刪除冗余索引。
(6)聯(lián)表查詢時,JOIN 列的數(shù)據(jù)類型必須相同,并且要建?索引。
(7)不在低基數(shù)列上建?索引,例如“性別”。 在低基數(shù)列上創(chuàng)建的索引查詢相比全表掃描不一定有性能優(yōu)勢,特別是當(dāng)存在回表成本時。
(8)選擇區(qū)分度(選擇率)大的列建立索引。組合索引中,區(qū)分度(選擇率)大的字段放在最前面。
(9)對過長的 Varchar 段建立索引。建議優(yōu)先考慮前綴索引,或添加 CRC32 或 MD5 偽列并建?索引。
(10)合理創(chuàng)建聯(lián)合索引,(a,b,c) 相當(dāng)于 (a) 、(a,b) 、(a,b,c)。
(11)合理使用覆蓋索引減少IO,避免排序。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 索引基礎(chǔ) 索引的類型 B-Tree索引 當(dāng)人們談?wù)撍饕龝r,如果沒有特別指明類型,那多半說的是B-Tree索引。存儲...
    coolcao閱讀 611評論 1 3
  • 創(chuàng)建高性能索引 索引是什么?有什么作用? 索引是存儲引擎用于快速找到記錄的一種數(shù)據(jù)結(jié)構(gòu) 如書的目錄索引一般,數(shù)據(jù)庫...
    esrever閱讀 716評論 0 0
  • 轉(zhuǎn)自:http://blog.csdn.net/lemon89/article/details/50193891 ...
    ywhu閱讀 778評論 0 1
  • 她是作為一個危機(jī)干預(yù)的個案被緊急介紹給我的。高學(xué)歷,工作穩(wěn)定。戀愛對象提出分手,她再三哀求竭力挽回,對方始終...
    入流亡所閱讀 287評論 0 0
  • 作業(yè)要求 打印直角三角形,從控制臺輸入直角三角形的高度(行數(shù))。 代碼 ...Console.WriteLine(...
    wlp小迷妹閱讀 130評論 0 0

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