国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化

這篇具有很好參考價(jià)值的文章主要介紹了8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。


本文是按照自己的理解進(jìn)行筆記總結(jié),如有不正確的地方,還望大佬多多指點(diǎn)糾正,勿噴。

本節(jié)課內(nèi)容:

1.什么是表設(shè)計(jì)的第一、第二、第三范式?
2.什么叫反范式化設(shè)計(jì)?
3.工作中的反范式實(shí)踐
4.InnoDB中的聚集索引和輔助索引
5.什么是回表和MRR?
6. InnoDB中的AHI自適應(yīng)哈希索引
7. InnoDB中的全文索引
8.面試題:什么是密集索引和稀疏索引?
9.辨析覆蓋索引/索引覆蓋
10.高性能的索引創(chuàng)建策略
11.索引選擇性和前綴索引
12.面試題:什么是三星索引?
13.高性能的索引維護(hù)實(shí)踐

1. 數(shù)據(jù)庫(kù)表設(shè)計(jì)

在數(shù)據(jù)庫(kù)表設(shè)計(jì)上有個(gè)很重要的設(shè)計(jì)準(zhǔn)則,稱(chēng)為范式設(shè)計(jì)。

1.1 范式化設(shè)計(jì)

1.1.1 什么是范式?

范式來(lái)自英文Normal Form,簡(jiǎn)稱(chēng)NF。MySQL是關(guān)系型數(shù)據(jù)庫(kù),但是要想設(shè)計(jì)—個(gè)好的關(guān)系,必須使關(guān)系滿(mǎn)足一定的約束條件,此約束已經(jīng)形成了規(guī)范,分成幾個(gè)等級(jí),一級(jí)比一級(jí)要求得嚴(yán)格。滿(mǎn)足這些規(guī)范的數(shù)據(jù)庫(kù)是簡(jiǎn)潔的、結(jié)構(gòu)明晰的,同時(shí),不會(huì)發(fā)生插入(insert)、刪除(delete)和更新(update)操作異常。反之則是亂七八糟,不僅給數(shù)據(jù)庫(kù)的編程人員制造麻煩,而且面目可憎,可能存儲(chǔ)了大量不需要的冗余信息。

目前關(guān)系數(shù)據(jù)庫(kù)有六種范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又稱(chēng)完美范式)。滿(mǎn)足最低要求的范式是第一范式(1NF)。在第一范式的基礎(chǔ)上進(jìn)一步滿(mǎn)足更多規(guī)范要求的稱(chēng)為第二范式(2NF),其余范式以次類(lèi)推。一般來(lái)說(shuō),數(shù)據(jù)庫(kù)只需滿(mǎn)足第三范式(3NF)就行了。

1.1.2 第一范式(1NF)

1、每一列屬性都是不可再分的屬性值,確保每一列的原子性;
2、兩列的屬性相近或相似或一樣,盡量合并屬性一樣的列,確保不產(chǎn)生冗余數(shù)據(jù);
3、單一屬性的列為基本數(shù)據(jù)類(lèi)型構(gòu)成;
4、設(shè)計(jì)出來(lái)的表都是簡(jiǎn)單的二維表。

定義: 屬于第一范式關(guān)系的所有屬性都不可再分,即數(shù)據(jù)項(xiàng)不可分。
理解: 第一范式強(qiáng)調(diào)數(shù)據(jù)表的原子性,是其他范式的基礎(chǔ)

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化
只第一范式來(lái)規(guī)范表格是遠(yuǎn)遠(yuǎn)不夠的,依然會(huì)存在數(shù)據(jù)冗余過(guò)大、刪除異常、插入異常、修改異常的問(wèn)題,此時(shí)就需要引入規(guī)范化概念,將其轉(zhuǎn)化為更標(biāo)準(zhǔn)化的表格,減少數(shù)據(jù)依賴(lài)。

1.1.2 第二范式(2NF)

  1. 第二范式(2NF)是在第一范式(1NF)的基礎(chǔ)上建立起來(lái)的,即滿(mǎn)足第二范式(2NF)必須先滿(mǎn)足第一范式(1NF)。
  2. 第二范式(2NF)要求實(shí)體的屬性完全依賴(lài)于主關(guān)鍵字。所謂完全依賴(lài)是指不能存在僅依賴(lài)主關(guān)鍵字一部分的屬性,如果存在,那么這個(gè)屬性和主關(guān)鍵字的這一部分應(yīng)該分離出來(lái)形成一個(gè)新的實(shí)體,新實(shí)體與原實(shí)體之間是一對(duì)多的關(guān)系

第二范式(2NF)要求數(shù)據(jù)庫(kù)表中的每個(gè)實(shí)例或行必須可以被惟一地區(qū)分。通常在實(shí)現(xiàn)來(lái)說(shuō),需要為表加上一個(gè)列,以存儲(chǔ)各個(gè)實(shí)例的惟一標(biāo)識(shí)。例如員工信息表中加上了員工編號(hào)(emp_id)列,因?yàn)槊總€(gè)員工的員工編號(hào)是惟一的,因此每個(gè)員工可以被惟一區(qū)分。這個(gè)惟一屬性列被稱(chēng)為主關(guān)鍵字或主鍵、主碼。

也就是說(shuō)要求表中只具有一個(gè)業(yè)務(wù)主鍵,而且第二范式(2NF)要求實(shí)體的屬性完全依賴(lài)于主關(guān)鍵字。所謂完全依賴(lài)是指不能存在僅依賴(lài)主關(guān)鍵字一部分的屬性。

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化

1.1.3 第三范式(3NF)

指每一個(gè)非主屬性既不部分依賴(lài)于也不傳遞依賴(lài)于業(yè)務(wù)主鍵,也就是在第二范式的基礎(chǔ)上消除了非主鍵對(duì)主鍵的傳遞依賴(lài)。例如,存在一個(gè)部門(mén)信息表,其中每個(gè)部門(mén)有部門(mén)編號(hào)(dept_id)、部門(mén)名稱(chēng)、部門(mén)簡(jiǎn)介等信息。那么在員工信息表中列出部門(mén)編號(hào)后就不能再將部門(mén)名稱(chēng)、部門(mén)簡(jiǎn)介等與部門(mén)有關(guān)的信息再加入員工信息表中。如果不存在部門(mén)信息表,則根據(jù)第三范式(3NF)也應(yīng)該構(gòu)建它,否則就會(huì)有大量的數(shù)據(jù)冗余。

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化

其中
產(chǎn)品 ID與訂單編號(hào)存在關(guān)聯(lián)關(guān)系
產(chǎn)品名稱(chēng)與訂單編號(hào)存在關(guān)聯(lián)關(guān)系
產(chǎn)品ID與產(chǎn)品名稱(chēng)存在關(guān)聯(lián)關(guān)系
訂單表里如果如果產(chǎn)品ID發(fā)生改變,同一個(gè)表里產(chǎn)品名稱(chēng)也要跟著改變,這樣不符合第三范式,應(yīng)該把產(chǎn)品名稱(chēng)這一列從訂單表中刪除。

范式說(shuō)明
真正的數(shù)據(jù)庫(kù)范式定義上,相當(dāng)難懂,比如第二范式(2NF)的定義“若某關(guān)系R屬于第一范式,且每一個(gè)非主屬性完全函數(shù)依賴(lài)于任何一個(gè)候選碼,則關(guān)系R屬于第二范式?!?,這里面有著大堆專(zhuān)業(yè)術(shù)語(yǔ)的堆疊,比如“函數(shù)依賴(lài)”、“碼”、“非主屬性”、與“完全函數(shù)依賴(lài)”等等,而且有完備的公式定義,需要仔細(xì)研究

1.2 反范式設(shè)計(jì)

1.2.1 什么叫反范式化設(shè)計(jì)

完全符合范式化的設(shè)計(jì)真的完美無(wú)缺嗎?很明顯在實(shí)際的業(yè)務(wù)查詢(xún)中會(huì)大量存在著表的關(guān)聯(lián)查詢(xún),而大量的表關(guān)聯(lián)很多的時(shí)候非常影響查詢(xún)的性能。

所謂得反范式化就是為了性能和讀取效率得考慮而適當(dāng)?shù)脤?duì)數(shù)據(jù)庫(kù)設(shè)計(jì)范式得要求進(jìn)行違反。允許存在少量得冗余,換句話(huà)來(lái)說(shuō)反范式化就是使用空間來(lái)?yè)Q取時(shí)間。

反范式設(shè)計(jì)-商品信息
下面是范式設(shè)計(jì)的商品信息表
8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化
商品信息和分類(lèi)信息經(jīng)常一起查詢(xún),所以把分類(lèi)信息也放到商品表里面,冗余存放

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化

1.3 范式化和反范式總結(jié)

1.3.1 范式化設(shè)計(jì)優(yōu)缺點(diǎn)

1、范式化的更新操作通常比反范式化要快。
2、當(dāng)數(shù)據(jù)較好地范式化時(shí),就只有很少或者沒(méi)有重復(fù)數(shù)據(jù),所以只需要修改更少的數(shù)據(jù)。
3、范式化的表通常更小,可以更好地放在內(nèi)存里,所以執(zhí)行操作會(huì)更快。
4、很少有多余的數(shù)據(jù)意味著檢索列表數(shù)據(jù)時(shí)更少需要DISTINCT或者GROUP BY語(yǔ)句。在非范式化的結(jié)構(gòu)中必須使用DISTINCT或者GROUPBY才能獲得一份唯一的列表,但是如果是一張單獨(dú)的表,很可能則只需要簡(jiǎn)單的查詢(xún)這張表就行了。
范式化設(shè)計(jì)的缺點(diǎn)是通常需要關(guān)聯(lián)。稍微復(fù)雜一些的查詢(xún)語(yǔ)句在符合范式的表上都可能需要至少一次關(guān)聯(lián),也許更多。這不但代價(jià)昂貴,也可能使一些索引策略無(wú)效。例如,范式化可能將列存放在不同的表中,而這些列如果在一個(gè)表中本可以屬于同一個(gè)索引。

1.3.2 反范式化設(shè)計(jì)優(yōu)缺點(diǎn)

1、反范式設(shè)計(jì)可以減少表的關(guān)聯(lián)
2、可以更好的進(jìn)行索引優(yōu)化。
反范式設(shè)計(jì)缺點(diǎn)也很明顯,
1、存在數(shù)據(jù)冗余及數(shù)據(jù)維護(hù)異常,
2、對(duì)數(shù)據(jù)的修改需要更多的成本。

實(shí)際工作中的反范式實(shí)現(xiàn)
冗余、緩存、匯總(實(shí)時(shí)還是定時(shí),根據(jù)需求的實(shí)時(shí)性來(lái))

計(jì)數(shù)器表(寫(xiě)熱點(diǎn)的分散)

搜索引擎(新增 + 查詢(xún))

1.3.3 性能提升-緩存和匯總

范式化和反范式化的各有優(yōu)劣,怎么選擇最佳的設(shè)計(jì)?

而現(xiàn)實(shí)也是,完全的范式化和完全的反范式化設(shè)計(jì)都是實(shí)驗(yàn)室里才有的東西,在真實(shí)世界中很少會(huì)這么極端地使用。在實(shí)際應(yīng)用中經(jīng)常需要混用
最常見(jiàn)的反范式化數(shù)據(jù)的方法復(fù)制或者緩存,在不同的表中存儲(chǔ)相同的特定列。
比如從父表冗余一些數(shù)據(jù)到子表的。前面我們看到的分類(lèi)信息放到商品表里面進(jìn)行冗余存放就是典型的例子。
緩存衍生值也是有用的。如果需要顯示每個(gè)用戶(hù)發(fā)了多少消息,可以每次執(zhí)行一個(gè)對(duì)用戶(hù)發(fā)送消息進(jìn)行count的子查詢(xún)來(lái)計(jì)算并顯示它,也可以在user表用戶(hù)中建一個(gè)消息發(fā)送數(shù)目的專(zhuān)門(mén)列,每當(dāng)用戶(hù)發(fā)新消息時(shí)更新這個(gè)值。
有需要時(shí)創(chuàng)建一張完全獨(dú)立的匯總表或緩存表也是提升性能的好辦法。

“緩存表”來(lái)表示存儲(chǔ)那些可以比較簡(jiǎn)單地從其他表獲?。ǖ敲看潍@取的速度比較慢)數(shù)據(jù)的表(例如,邏輯上冗余的數(shù)據(jù))。而“匯總表”時(shí),則保存的是使用GROUP BY語(yǔ)句聚合數(shù)據(jù)的表。
在使用緩存表和匯總表時(shí),有個(gè)關(guān)鍵點(diǎn)是如何維護(hù)緩存表和匯總表中的數(shù)據(jù),常用的有兩種方式,實(shí)時(shí)維護(hù)數(shù)據(jù)定期重建,這個(gè)取決于應(yīng)用程序,不過(guò)一般來(lái)說(shuō),緩存表用實(shí)時(shí)維護(hù)數(shù)據(jù)更多點(diǎn),往往在一個(gè)事務(wù)中同時(shí)更新數(shù)據(jù)本表和緩存表,匯總表則用定期重建更多,使用定時(shí)任務(wù)對(duì)匯總表進(jìn)行更新。

1.3.4 性能提升-計(jì)數(shù)器表

計(jì)數(shù)器表在Web應(yīng)用中很常見(jiàn)。比如網(wǎng)站點(diǎn)擊數(shù)、用戶(hù)的朋友數(shù)、文件下載次數(shù)等。對(duì)于高并發(fā)下的處理,首先可以創(chuàng)建一張獨(dú)立的表存儲(chǔ)計(jì)數(shù)器,這樣可使計(jì)數(shù)器表小且快,并且可以使用一些更高級(jí)的技巧。

比如假設(shè)有一個(gè)計(jì)數(shù)器表,只有一行數(shù)據(jù),記錄網(wǎng)站的點(diǎn)擊次數(shù),網(wǎng)站的每次點(diǎn)擊都會(huì)導(dǎo)致對(duì)計(jì)數(shù)器進(jìn)行更新,問(wèn)題在于,對(duì)于任何想要更新這一行的事務(wù)來(lái)說(shuō),這條記錄上都有一個(gè)全局的互斥鎖(mutex)。這會(huì)使得這些事務(wù)只能串行執(zhí)行,會(huì)嚴(yán)重限制系統(tǒng)的并發(fā)能力。

怎么改進(jìn)呢?可以將計(jì)數(shù)器保存在多行中,每次隨機(jī)選擇一行進(jìn)行更新。在具體實(shí)現(xiàn)上,可以增加一個(gè)槽(slot)字段,然后預(yù)先在這張表增加100行或者更多數(shù)據(jù),當(dāng)對(duì)計(jì)數(shù)器更新時(shí),選擇一個(gè)隨機(jī)的槽(slot)進(jìn)行更新即可。
這種解決思路其實(shí)就是寫(xiě)熱點(diǎn)的分散,在JDK的JDK1.8中新的原子類(lèi)LongAdder也是這種處理方式,而我們?cè)趯?shí)際的緩沖中間件Redis等的使用、架構(gòu)設(shè)計(jì)中,可以采用這種寫(xiě)熱點(diǎn)的分散的方式,當(dāng)然架構(gòu)設(shè)計(jì)中對(duì)于寫(xiě)熱點(diǎn)還有削峰填谷的處理方式,這種在MySQL的實(shí)現(xiàn)中也有體現(xiàn),我們后面會(huì)講到。

1.3.5 反范式設(shè)計(jì)-分庫(kù)分表中的查詢(xún)

例如,用戶(hù)購(gòu)買(mǎi)了商品,需要將交易記錄保存下來(lái),那么如果按照買(mǎi)家的緯度分表,則每個(gè)買(mǎi)家的交易記錄都被保存在同一表中, 我們可以很快、 很方便地査到某個(gè)買(mǎi)家的購(gòu)買(mǎi)情況, 但是某個(gè)商品被購(gòu)買(mǎi)的交易數(shù)據(jù)很有可能分布在多張表中, 査找起來(lái)比較麻煩 。 反之, 按照商品維度分表, 則可以很方便地査找到該商品的購(gòu)買(mǎi)情況, 但若要査找到買(mǎi)家的交易記錄, 則會(huì)比較麻煩 。
所以常見(jiàn)的解決方式如下。
( 1 ) 在多個(gè)分片表查詢(xún)后合并數(shù)據(jù)集, 這種方式的效率很低。
( 2 ) 記錄兩份數(shù)據(jù), 一份按照買(mǎi)家緯度分表, 一份按照商品維度分表,
( 3 ) 通過(guò)搜索引擎解決, 但如果實(shí)時(shí)性要求很高, 就需要實(shí)現(xiàn)實(shí)時(shí)搜索
在某電商交易平臺(tái)下, 可能有買(mǎi)家査詢(xún)自己在某一時(shí)間段的訂單, 也可能有賣(mài)家査詢(xún)自已在某一時(shí)間段的訂單, 如果使用了分庫(kù)分表方案, 則這兩個(gè)需求是難以滿(mǎn)足的, 因此, 通用的解決方案是, 在交易生成時(shí)生成一份按照買(mǎi)家分片的數(shù)據(jù)副本和一份按照賣(mài)家分片的數(shù)據(jù)副本,查詢(xún)時(shí)分別滿(mǎn)足之前的兩個(gè)需求,因此,查詢(xún)的數(shù)據(jù)和交易的數(shù)據(jù)可能是分別存儲(chǔ)的,并從不同的系統(tǒng)提供接口。

總結(jié)經(jīng)驗(yàn)

1.實(shí)際設(shè)計(jì)中,先按照3范式設(shè)計(jì),盡可能去通過(guò)設(shè)計(jì)索引和優(yōu)化sql,如果逐漸發(fā)現(xiàn)性能跟不上了,開(kāi)始考慮做反范式化設(shè)計(jì)。也就是,盡可能遵循范式化設(shè)計(jì),當(dāng)范式化設(shè)計(jì)影響到性能的時(shí)候毫不猶豫啟動(dòng)反范式化設(shè)計(jì)。
2.反范式化的核心:空間換時(shí)間

2. 高性能索引

InnoDB中的索引是按照B+樹(shù)來(lái)組織的,我們知道B+樹(shù)的葉子節(jié)點(diǎn)用來(lái)放數(shù)據(jù)的,但是放什么數(shù)據(jù)呢?索引自然是要放的,因?yàn)锽+樹(shù)的作用本來(lái)就是為了快速檢索數(shù)據(jù)而提出的一種數(shù)據(jù)結(jié)構(gòu),不放索引放什么呢?但是數(shù)據(jù)庫(kù)中的表,數(shù)據(jù)才是我們真正需要的數(shù)據(jù),索引只是輔助數(shù)據(jù),甚至于一個(gè)表可以沒(méi)有自定義索引。InnoDB中的數(shù)據(jù)到底是如何組織的?

2.1 聚集索引/聚簇索引

InnoDB中使用了聚集索引,就是將表的主鍵用來(lái)構(gòu)造一棵B+樹(shù),并且將整張表的行記錄數(shù)據(jù)存放在該B+樹(shù)的葉子節(jié)點(diǎn)中。也就是所謂的索引即數(shù)據(jù),數(shù)據(jù)即索引。由于聚集索引是利用表的主鍵構(gòu)建的,所以每張表只能擁有一個(gè)聚集索引。

聚集索引的葉子節(jié)點(diǎn)就是數(shù)據(jù)頁(yè)。換句話(huà)說(shuō),數(shù)據(jù)頁(yè)上存放的是完整的每行記錄。因此聚集索引的一個(gè)優(yōu)點(diǎn)就是:通過(guò)過(guò)聚集索引能獲取完整的整行數(shù)據(jù)。另一個(gè)優(yōu)點(diǎn)是:對(duì)于主鍵的排序查找和范圍查找速度非???。
如果我們沒(méi)有定義主鍵呢?MySQL會(huì)使用唯一性索引,沒(méi)有唯一性索引,MySQL也會(huì)創(chuàng)建一個(gè)隱含列RowID來(lái)做主鍵,然后用這個(gè)主鍵來(lái)建立聚集索引。
8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化

2.2 輔助索引/二級(jí)索引

上邊介紹的聚簇索引只能在搜索條件是主鍵值時(shí)才能發(fā)揮作用,因?yàn)锽+樹(shù)中的數(shù)據(jù)都是按照主鍵進(jìn)行排序的,那如果我們想以別的列作為搜索條件怎么辦?我們一般會(huì)建立多個(gè)索引,這些索引被稱(chēng)為輔助索引/二級(jí)索引。
對(duì)于輔助索引(Secondary Index,也稱(chēng)二級(jí)索引、非聚集索引),葉子節(jié)點(diǎn)并不包含行記錄的全部數(shù)據(jù)。葉子節(jié)點(diǎn)除了包含鍵值以外,每個(gè)葉子節(jié)點(diǎn)中的索引行中還包含了相應(yīng)行數(shù)據(jù)的聚集索引鍵。

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化
比如輔助索引index(node),那么葉子節(jié)點(diǎn)中包含的數(shù)據(jù)就包括了(主鍵、note)。

2.3 回表

輔助索引的存在并不影響數(shù)據(jù)在聚集索引中的組織,因此每張表上可以有多個(gè)輔助索引。當(dāng)通過(guò)輔助索引來(lái)尋找數(shù)據(jù)時(shí),InnoDB存儲(chǔ)引擎會(huì)遍歷輔助索引并通過(guò)葉級(jí)別的指針獲得指向主鍵索引的主鍵,然后再通過(guò)主鍵索引(聚集索引)來(lái)找到一個(gè)完整的行記錄。這個(gè)過(guò)程也被稱(chēng)為回表。也就是根據(jù)輔助索引的值查詢(xún)一條完整的用戶(hù)記錄需要使用到2棵B+樹(shù)----一次輔助索引,一次聚集索引。

為什么我們還需要一次回表操作呢?直接把完整的用戶(hù)記錄放到輔助索引d的葉子節(jié)點(diǎn)不就好了么?

如果把完整的用戶(hù)記錄放到葉子節(jié)點(diǎn)是可以不用回表,但是太占地方了,相當(dāng)于每建立一棵B+樹(shù)都需要把所有的用戶(hù)記錄再都拷貝一遍,這就有點(diǎn)太浪費(fèi)存儲(chǔ)空間了。而且每次對(duì)數(shù)據(jù)的變化要在所有包含數(shù)據(jù)的索引中全部都修改一次,性能也非常低下。

很明顯,回表的記錄越少,性能提升就越高,需要回表的記錄越多,使用二級(jí)索引的性能就越低,甚至讓某些查詢(xún)寧愿使用全表掃描也不使用二級(jí)索引。
那什么時(shí)候采用全表掃描的方式,什么時(shí)候使用采用二級(jí)索引 + 回表的方式去執(zhí)行查詢(xún)呢?這個(gè)就是查詢(xún)優(yōu)化器做的工作,查詢(xún)優(yōu)化器會(huì)事先對(duì)表中的記錄計(jì)算一些統(tǒng)計(jì)數(shù)據(jù),然后再利用這些統(tǒng)計(jì)數(shù)據(jù)根據(jù)查詢(xún)的條件來(lái)計(jì)算一下需要回表的記錄數(shù),需要回表的記錄數(shù)越多,就越傾向于使用全表掃描,反之傾向于使用二級(jí)索引 + 回表的方式。

2.4 MRR

從上文可以看出,每次從二級(jí)索引中讀取到一條記錄后,就會(huì)根據(jù)該記錄的主鍵值執(zhí)行回表操作。而在某個(gè)掃描區(qū)間中的二級(jí)索引記錄的主鍵值是無(wú)序的,也就是說(shuō)這些二級(jí)索引記錄對(duì)應(yīng)的聚簇索引記錄所在的頁(yè)面的頁(yè)號(hào)是無(wú)序的。
每次執(zhí)行回表操作時(shí)都相當(dāng)于要隨機(jī)讀取一個(gè)聚簇索引頁(yè)面,而這些隨機(jī)IO帶來(lái)的性能開(kāi)銷(xiāo)比較大。MySQL中提出了一個(gè)名為Disk-Sweep Multi-Range Read (MRR,多范圍讀取)的優(yōu)化措施,即先讀取一部分二級(jí)索引記錄,將它們的主鍵值排好序之后再統(tǒng)一執(zhí)行回表操作。

相對(duì)于每讀取一條二級(jí)索引記錄就立即執(zhí)行回表操作,這樣會(huì)節(jié)省一些IO開(kāi)銷(xiāo)。使用這個(gè) MRR優(yōu)化措施的條件比較苛刻,所以我們直接認(rèn)為每讀取一條二級(jí)索引記錄就立即執(zhí)行回表操作。MRR的詳細(xì)信息,可以查詢(xún)官方文檔。

2.5 聯(lián)合索引/復(fù)合索引

前面我們對(duì)索引的描述,隱含了一個(gè)條件,那就是構(gòu)建索引的字段只有一個(gè),但實(shí)踐工作中構(gòu)建索引的完全可以是多個(gè)字段。所以,將表上的多個(gè)列組合起來(lái)進(jìn)行索引我們稱(chēng)之為聯(lián)合索引或者復(fù)合索引,比如index(a,b)就是將a,b兩個(gè)列組合起來(lái)構(gòu)成一個(gè)索引。
千萬(wàn)要注意一點(diǎn),建立聯(lián)合索引只會(huì)建立1棵B+樹(shù),多個(gè)列分別建立索引會(huì)分別以每個(gè)列則建立B+樹(shù),有幾個(gè)列就有幾個(gè)B+樹(shù),比如,index(note)、index(b),就分別對(duì)note,b兩個(gè)列各構(gòu)建了一個(gè)索引。

index(note,b)在索引構(gòu)建上,包含了兩個(gè)意思:
1、先把各個(gè)記錄按照note列進(jìn)行排序。
2、在記錄的note列相同的情況下,采用b列進(jìn)行排序

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化

2.6 自適應(yīng)哈希索引

InnoDB存儲(chǔ)引擎除了我們前面所說(shuō)的各種索引,還有一種自適應(yīng)哈希索引,我們知道B+樹(shù)的查找次數(shù),取決于B+樹(shù)的高度,在生產(chǎn)環(huán)境中,B+樹(shù)的高度一般為3-4層,故需要3~4次的IO查詢(xún)。

所以在InnoDB存儲(chǔ)引擎內(nèi)部自己去監(jiān)控索引表,如果監(jiān)控到某個(gè)索引經(jīng)常用,那么就認(rèn)為是熱數(shù)據(jù),然后內(nèi)部自己創(chuàng)建一個(gè)hash索引,稱(chēng)之為自適應(yīng)哈希索引( Adaptive Hash Index,AHI),創(chuàng)建以后,如果下次又查詢(xún)到這個(gè)索引,那么直接通過(guò)hash算法推導(dǎo)出記錄的地址,直接一次就能查到數(shù)據(jù),比重復(fù)去B+tree索引中查詢(xún)?nèi)拇喂?jié)點(diǎn)的效率高了不少。

InnoDB存儲(chǔ)引擎使用的哈希函數(shù)采用除法散列方式,其沖突機(jī)制采用鏈表方式。注意,對(duì)于自適應(yīng)哈希索引僅是數(shù)據(jù)庫(kù)自身創(chuàng)建并使用的,我們并不能對(duì)其進(jìn)行干預(yù)。通過(guò)命令show engine innodb status\G可以看到當(dāng)前自適應(yīng)哈希索引的使用狀況,如:

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化

哈希索引只能用來(lái)搜索等值的查詢(xún),如 SELECT* FROM table WHERE index co=xxx。而對(duì)于其他查找類(lèi)型,如范圍查找,是不能使用哈希索引的,
因此這里會(huì)顯示non- hash searches/s的統(tǒng)計(jì)情況。通過(guò) hash searches: non-hash searches可以大概了解使用哈希索引后的效率。

由于AHI是由 InnoDB存儲(chǔ)引擎控制的,因此這里的信息只供我們參考。不過(guò)我們可以通過(guò)觀察 SHOW ENGINE INNODB STATUS的結(jié)果及參數(shù) innodb_adaptive_hash_index來(lái)考慮是禁用啟動(dòng)此特性,默認(rèn)AHI為開(kāi)啟狀態(tài)。

什么時(shí)候需要禁用呢?如果發(fā)現(xiàn)監(jiān)視索引查找和維護(hù)哈希索引結(jié)構(gòu)的額外開(kāi)銷(xiāo)遠(yuǎn)遠(yuǎn)超過(guò)了自適應(yīng)哈希索引帶來(lái)的性能提升就需要關(guān)閉這個(gè)功能。

同時(shí)在MySQL 5.7中,自適應(yīng)哈希索引搜索系統(tǒng)被分區(qū)。每個(gè)索引都綁定到一個(gè)特定的分區(qū),每個(gè)分區(qū)都由一個(gè)單獨(dú)的 latch 鎖保護(hù)。分區(qū)由 innodb_adaptive_hash_index_parts 配置選項(xiàng)控制 。在早期版本中,自適應(yīng)哈希索引搜索系統(tǒng)受到單個(gè) latch 鎖的保護(hù),這可能成為繁重工作負(fù)載下的爭(zhēng)用點(diǎn)。innodb_adaptive_hash_index_parts 默認(rèn)情況下,該選項(xiàng)設(shè)置為8。最大設(shè)置為512。當(dāng)然禁用或啟動(dòng)此特性和調(diào)整分區(qū)個(gè)數(shù)這個(gè)應(yīng)該是DBA的工作,我們了解即可。

InnoDB引擎有三大特性(這個(gè)是面試的時(shí)候很容易被問(wèn)到的。)

2.7 全文檢索之倒排索引

什么是全文檢索(Full-Text Search)?

它是將存儲(chǔ)于數(shù)據(jù)庫(kù)中的整本書(shū)或整篇文章中的任意內(nèi)容信息查找出來(lái)的技術(shù)。它可以根據(jù)需要獲得全文中有關(guān)章、節(jié)、段、句、詞等信息,也可以進(jìn)行各種統(tǒng)計(jì)和分析。我們比較熟知的Elasticsearch、Solr等就是全文檢索引擎,底層都是基于Apache Lucene的。

舉個(gè)例子,現(xiàn)在我們要保存唐宋詩(shī)詞,數(shù)據(jù)庫(kù)中我們們會(huì)怎么設(shè)計(jì)?詩(shī)詞表我們可能的設(shè)計(jì)如下:

朝代 作者 詩(shī)詞年代 標(biāo)題 詩(shī)詞全文
李白 靜夜思 床前明月光,疑是地上霜。 舉頭望明月,低頭思故鄉(xiāng)。
李清照 如夢(mèng)令 常記溪亭日暮,沉醉不知?dú)w路,興盡晚回舟,誤入藕花深處。爭(zhēng)渡,爭(zhēng)渡,驚起一灘鷗鷺。

要根據(jù)朝代或者作者尋找詩(shī),都很簡(jiǎn)單,比如"select 詩(shī)詞全文 from 詩(shī)詞表 where作者=‘李白’",如果數(shù)據(jù)很多,查詢(xún)速度很慢,怎么辦?

我們可以在對(duì)應(yīng)的查詢(xún)字段上建立索引加速查詢(xún)。

但是如果我們現(xiàn)在有個(gè)需求:要求找到包含"望"字的詩(shī)詞怎么辦?

“select 詩(shī)詞全文 from 詩(shī)詞表 where詩(shī)詞全文 like’%望%’”,這個(gè)意味著要掃描庫(kù)中的詩(shī)詞全文字段,逐條比對(duì),找出所有包含關(guān)鍵詞"望"字的記錄。基本上,數(shù)據(jù)庫(kù)中一般的SQL優(yōu)化手段都是用不上的。數(shù)量少,大概性能還能接受,如果數(shù)據(jù)量稍微大點(diǎn),就完全無(wú)法接受了,更何況在互聯(lián)網(wǎng)這種海量數(shù)據(jù)的情況下呢?怎么解決這個(gè)問(wèn)題呢,用倒排索引。

比如現(xiàn)在有:

蜀道難(唐)李白 蜀道之難難于上青天,側(cè)身西望長(zhǎng)咨嗟。
靜夜思(唐)李白 舉頭望明月,低頭思故鄉(xiāng)。
春臺(tái)望(唐)李隆基 暇景屬三春,高臺(tái)聊四望。
鶴沖天(宋)柳永 黃金榜上,偶失龍頭望。明代暫遺賢,如何向?未遂風(fēng)云便,爭(zhēng)不恣狂蕩。何須論得喪?才子詞人,自是白衣卿相。煙花巷陌,依約丹青屏障。幸有意中人,堪尋訪(fǎng)。且恁偎紅翠,風(fēng)流事,平生暢。青春都一餉。忍把浮名,換了淺斟低唱!

都有字,于是我們可以這么保存

序號(hào) 關(guān)鍵字 蜀道難 靜夜思 春臺(tái)望 鶴沖天
1

如果查哪個(gè)詩(shī)詞中包含,怎么辦,上述的表格可以繼續(xù)填入新的記錄

序號(hào) 關(guān)鍵字 蜀道難 靜夜思 春臺(tái)望 鶴沖天
2

其實(shí),上述詩(shī)詞的中每個(gè)字都可以作為關(guān)鍵字,然后建立關(guān)鍵字和文檔之間的對(duì)應(yīng)關(guān)系,也就是標(biāo)識(shí)關(guān)鍵字被哪些文檔包含。

所以,倒排索引就是,將文檔中包含的關(guān)鍵字全部提取處理,然后再將關(guān)鍵字和文檔之間的對(duì)應(yīng)關(guān)系保存起來(lái),最后再對(duì)關(guān)鍵字本身做索引排序。用戶(hù)在檢索某一個(gè)關(guān)鍵字是,先對(duì)關(guān)鍵字的索引進(jìn)行查找,再通過(guò)關(guān)鍵字與文檔的對(duì)應(yīng)關(guān)系找到所在文檔。

在存儲(chǔ)在關(guān)系型數(shù)據(jù)庫(kù)中的數(shù)據(jù),需要我們事先分析將數(shù)據(jù)拆分為不同的字段,而在es這類(lèi)的存儲(chǔ)中,需要應(yīng)用程序根據(jù)規(guī)則自動(dòng)提取關(guān)鍵字,并形成對(duì)應(yīng)關(guān)系。

這些預(yù)先提取的關(guān)鍵字,在全文檢索領(lǐng)域一般被稱(chēng)為term(詞項(xiàng)),文檔的詞項(xiàng)提取在es中被稱(chēng)為文檔分析,這是全文檢索很核心的過(guò)程,必須要區(qū)分哪些是詞項(xiàng),哪些不是,比如很多場(chǎng)景下,apple和apples是同一個(gè)東西,望和看其實(shí)是同一個(gè)動(dòng)作。

2.8 MySQL中的全文索引

MySQL 5.6 以前的版本,只有 MyISAM 存儲(chǔ)引擎支持全文索引。從InnoDB 1.2.x版本開(kāi)始,InnoDB存儲(chǔ)引擎開(kāi)始支持全文檢索,對(duì)應(yīng)的MySQL版本是5.6.x系列。

注意,不管什么引擎,只有字段的數(shù)據(jù)類(lèi)型為 char、varchar、text 及其系列才可以建全文索引。

不過(guò)MySQL從設(shè)計(jì)之初就是關(guān)系型數(shù)據(jù)庫(kù),存儲(chǔ)引擎雖然支持全文檢索,整體架構(gòu)上對(duì)全文檢索支持并不好而且限制很多,比如每張表只能有一個(gè)全文檢索的索引,不支持沒(méi)有單詞界定符( delimiter)的語(yǔ)言,如中文、日語(yǔ)、韓語(yǔ)等。

所以如果有大批量或者專(zhuān)門(mén)的全文檢索需求,還是應(yīng)該選擇專(zhuān)門(mén)的全文檢索引擎,畢竟Elastic靠著全文檢索起家,然后產(chǎn)品化、公司化后依賴(lài)全文檢索不斷擴(kuò)充產(chǎn)品線(xiàn)和應(yīng)用場(chǎng)景,并推出商業(yè)版本的解決方案然后融資上市,現(xiàn)在的市值已達(dá)100億美元。

具體如何使用InnoDB存儲(chǔ)引擎的全文檢索,只提供簡(jiǎn)單的使用說(shuō)明,更多的詳情請(qǐng)自行查閱相關(guān)官方文檔或者書(shū)籍,官方文檔路徑:https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html

創(chuàng)建表時(shí)使用全文索引

創(chuàng)建表時(shí)創(chuàng)建全文索引
create table fulltext_test (
    id int(11) NOT NULL AUTO_INCREMENT,
    content text NOT NULL,
    tag varchar(255),
    PRIMARY KEY (id),
    FULLTEXT KEY content_tag_fulltext(content,tag)  
) DEFAULT CHARSET=utf8;
在已存在的表上創(chuàng)建全文索引
create fulltext index content_tag_fulltext
    on fulltext_test(content,tag);
通過(guò) SQL 語(yǔ)句 ALTER TABLE 創(chuàng)建全文索引
alter table fulltext_test
    add fulltext index content_tag_fulltext(content,tag);

2.9 總結(jié):MySQL有哪些索引類(lèi)型

數(shù)據(jù)結(jié)構(gòu)角度可分為B+樹(shù)索引、哈希索引、以及FULLTEXT索引(現(xiàn)在MyISAM和InnoDB引擎都支持了)和R-Tree索引(用于對(duì)GIS數(shù)據(jù)類(lèi)型創(chuàng)建SPATIAL索引);

物理存儲(chǔ)角度可分為聚集索引(clustered index)、非聚集索引(non-clustered index);

邏輯角度可分為主鍵索引、普通索引,或者單列索引、多列索引、唯一索引、非唯一索引等等。

面試題:Innodb存儲(chǔ)引擎的三大特性:
自適應(yīng)hash索引、雙寫(xiě)緩存區(qū)、BufferPool

面試題:什么是密集索引和稀疏索引?
密集索引的定義:葉子節(jié)點(diǎn)保存的不只是鍵值,還保存了位于同一行記錄里的其他列的信息,由于密集索引決定了表的物理排列順序,一個(gè)表只有一個(gè)物理排列順序,所以一個(gè)表只能創(chuàng)建一個(gè)密集索引。
稀疏索引:葉子節(jié)點(diǎn)僅保存了鍵位信息以及該行數(shù)據(jù)的地址,有的稀疏索引只保存了鍵位信息機(jī)器主鍵。

mysam存儲(chǔ)引擎,不管是主鍵索引,唯一鍵索引還是普通索引都是稀疏索引,innodb存儲(chǔ)引擎:有且只有一個(gè)密集索引。

所以,密集索引就是innodb存儲(chǔ)引擎里的聚簇索引稀疏索引就是innodb存儲(chǔ)引擎里的普通二級(jí)索引。

2.10 辨析覆蓋索引/索引覆蓋

既然多個(gè)列可以組合起來(lái)構(gòu)建為聯(lián)合索引,那么輔助索引自然也可以由多個(gè)列組成。

覆蓋索引也是我們經(jīng)常見(jiàn)到的名詞,InnoDB存儲(chǔ)引擎支持覆蓋索引(covering index,或稱(chēng)索引覆蓋),即從輔助索引中就可以得到查詢(xún)的記錄,而不需要查詢(xún)聚集索引中的記錄。使用覆蓋索引的一個(gè)好處是輔助索引不包含整行記錄的所有信息,故其大小要遠(yuǎn)小于聚集索引,因此可以減少大量的IO操作。所以記住,覆蓋索引可以視為索引優(yōu)化的一種方式,而并不是索引類(lèi)型的一種。

除了覆蓋索引這個(gè)概念外,在索引優(yōu)化的范圍內(nèi),還有前綴索引、三星索引等一系列概念,都會(huì)在后文補(bǔ)充。

覆蓋索引不是真真正正的索引,屬于索引優(yōu)化的一種方式。把回表這個(gè)動(dòng)作給去除了。

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化

2.11 深入思考索引在查詢(xún)中的使用

索引在查詢(xún)中的作用到底是什么?在我們的查詢(xún)中發(fā)揮著什么樣的作用呢? 請(qǐng)記?。?/code>

1、一個(gè)索引就是一個(gè)B+樹(shù),索引讓我們的查詢(xún)可以快速定位和掃描到我們需要的數(shù)據(jù)記錄上,加快查詢(xún)的速度。
2、一個(gè)select查詢(xún)語(yǔ)句在執(zhí)行過(guò)程中一般最多能使用一個(gè)二級(jí)索引來(lái)加快查詢(xún),即使在where條件中用了多個(gè)二級(jí)索引。

索引的代價(jià)
世界上從來(lái)沒(méi)有只有好處沒(méi)有壞處的東西,如果你有,請(qǐng)你一定要告訴我,讓我也感受一下。雖然索引是個(gè)好東西,在學(xué)習(xí)如何更好的使用索引之前先要了解一下使用它的代價(jià),它在空間和時(shí)間上都會(huì)拖后腿。

空間上的代價(jià)
這個(gè)是顯而易見(jiàn)的,每建立一個(gè)索引都要為它建立一棵B+樹(shù),每一棵B+樹(shù)的每一個(gè)節(jié)點(diǎn)都是一個(gè)數(shù)據(jù)頁(yè),一個(gè)頁(yè)默認(rèn)會(huì)占用16KB的存儲(chǔ)空間,一棵很大的B+樹(shù)由許多數(shù)據(jù)頁(yè)組成會(huì)占據(jù)很多的存儲(chǔ)空間。

時(shí)間上的代價(jià)
每次對(duì)表中的數(shù)據(jù)進(jìn)行增、刪、改操作時(shí),都需要去修改各個(gè)B+樹(shù)索引。而且我們講過(guò),B+樹(shù)每層節(jié)點(diǎn)都是按照索引列的值從小到大的順序排序而組成了雙向鏈表。不論是葉子節(jié)點(diǎn)中的記錄,還是非葉子內(nèi)節(jié)點(diǎn)中的記錄都是按照索引列的值從小到大的順序而形成了一個(gè)單向鏈表。
而增、刪、改操作可能會(huì)對(duì)節(jié)點(diǎn)和記錄的排序造成破壞,所以存儲(chǔ)引擎需要額外的時(shí)間進(jìn)行一些記錄移位,頁(yè)面分裂、頁(yè)面回收的操作來(lái)維護(hù)好節(jié)點(diǎn)和記錄的排序。如果我們建了許多索引,每個(gè)索引對(duì)應(yīng)的B+樹(shù)都要進(jìn)行相關(guān)的維護(hù)操作,這必然會(huì)對(duì)性能造成影響。
既然索引這么有用,我們是不是創(chuàng)建越多越好?既然索引有代價(jià),我們還是別創(chuàng)建了吧?當(dāng)然不是!按照經(jīng)驗(yàn),一般來(lái)說(shuō),一張表6-7個(gè)索引以下都能夠取得比較好的性能權(quán)衡。
那么創(chuàng)建索引的時(shí)候有什么好的策略讓我們充分利用索引呢?

2.12 高性能的索引創(chuàng)建策略

正確地創(chuàng)建和使用索引是實(shí)現(xiàn)高性能查詢(xún)的基礎(chǔ)。前面我們已經(jīng)了解了索引相關(guān)的數(shù)據(jù)結(jié)構(gòu),各種類(lèi)型的索引及其對(duì)應(yīng)的優(yōu)缺點(diǎn)。現(xiàn)在我們一起來(lái)看看如何真正地發(fā)揮這些索引的優(yōu)勢(shì)。

2.12.1 索引列的類(lèi)型盡量小

我們?cè)诙x表結(jié)構(gòu)的時(shí)候要顯式的指定列的類(lèi)型,以整數(shù)類(lèi)型為例,有TTNYINT、NEDUMNT、INT、BIGTNT這么幾種,它們占用的存儲(chǔ)空間依次遞增,我們這里所說(shuō)的類(lèi)型大小指的就是該類(lèi)型表示的數(shù)據(jù)范圍的大小。能表示的整數(shù)范圍當(dāng)然也是依次遞增,如果我們想要對(duì)某個(gè)整數(shù)列建立索引的話(huà),在表示的整數(shù)范圍允許的情況下,盡量讓索引列使用較小的類(lèi)型,比如我們能使用INT就不要使用BIGINT,能使用NEDIUMINT就不要使用INT,這是因?yàn)?

  • 數(shù)據(jù)類(lèi)型越小,在查詢(xún)時(shí)進(jìn)行的比較操作越快(CPU層次)
  • 數(shù)據(jù)類(lèi)型越小,索引占用的存儲(chǔ)空間就越少,在一個(gè)數(shù)據(jù)頁(yè)內(nèi)就可以放下更多的記錄,從而減少磁盤(pán)/0帶來(lái)的性能損耗,也就意味著可以把更多的數(shù)據(jù)頁(yè)緩存在內(nèi)存中,從而加快讀寫(xiě)效率。

這個(gè)建議對(duì)于表的主鍵來(lái)說(shuō)更加適用,因?yàn)椴粌H是聚簇索引中會(huì)存儲(chǔ)主鍵值,其他所有的二級(jí)索引的節(jié)點(diǎn)處都會(huì)存儲(chǔ)一份記錄的主鍵值,如果主鍵適用更小的數(shù)據(jù)類(lèi)型,也就意味著節(jié)省更多的存儲(chǔ)空間和更高效的I/0。

2.12.2 利用索引選擇性和前綴索引

索引的選擇性/離散性

創(chuàng)建索引應(yīng)該選擇選擇性/離散性高的列。索引的選擇性/離散性是指,不重復(fù)的索引值(也稱(chēng)為基數(shù),cardinality)和數(shù)據(jù)表的記錄總數(shù)(N)的比值,范圍從1/N到1之間。索引的選擇性越高則查詢(xún)效率越高,因?yàn)檫x擇性高的索引可以讓MySQL在查找時(shí)過(guò)濾掉更多的行。唯一索引的選擇性是1,這是最好的索引選擇性,性能也是最好的。

很差的索引選擇性就是列中的數(shù)據(jù)重復(fù)度很高,比如性別字段,不考慮政治正確的情況下,只有兩者可能,男或女。那么我們?cè)诓樵?xún)時(shí),即使使用這個(gè)索引,從概率的角度來(lái)說(shuō),依然可能查出一半的數(shù)據(jù)出來(lái)。

比如下面這個(gè)表

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化
哪列做為索引字段最好?當(dāng)然是姓名字段,因?yàn)槔锩娴臄?shù)據(jù)沒(méi)有任何重復(fù),性別字段是最不適合做索引的,因?yàn)閿?shù)據(jù)的重復(fù)度非常高。
怎么算索引的選擇性/離散性?比如order_exp這個(gè)表:
select COUNT(DISTINCT order_no)/count(*) cnt from order_exp;
8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化
select COUNT(DISTINCT order_status)/count(*) cnt from order_exp;

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化
很明顯,order_no列上的索引就比order_status列上的索引的選擇性就要好,原因很簡(jiǎn)單,因?yàn)閛rder_status列中的值只有-1,0,1三種。

2.12.3 前綴索引

有時(shí)候需要索引很長(zhǎng)的字符列,這會(huì)讓索引變得大且慢。一個(gè)策略是前面提到過(guò)的模擬哈希索引。

模擬哈希索引:
order_exp表中order_note字段很長(zhǎng),想把它作為一個(gè)索引,我們可以增加一個(gè)order_not_hash字段來(lái)存儲(chǔ)order_note的哈希值,然后在order_not_hash上建立索引,相對(duì)于之前的索引速度會(huì)有明顯提升,一個(gè)是對(duì)完整的 order_note做索引,而后者則是用整數(shù)哈希值做索引,顯然數(shù)字的比較比字符串的匹配要高效得多。

但是缺陷也很明顯:
1、需要額外維護(hù)order_not_hash字段;
2、哈希算法的選擇決定了哈希沖突的概率,不良的哈希算法會(huì)導(dǎo)致重復(fù)值很多;
3、不支持范圍查找。

還可以做些什么改進(jìn)呢?還可以索引開(kāi)始的部分字符,這樣可以大大節(jié)約索引空間,從而提高索引效率。但這樣也會(huì)降低索引的選擇性。一般情況下我們需要保證某個(gè)列前綴的選擇性也是足夠高的,以滿(mǎn)足查詢(xún)性能。(尤其對(duì)于BLOB、TEXT或者很長(zhǎng)的VARCHAR類(lèi)型的列,應(yīng)該使用前綴索引,因?yàn)镸ySQL不允許索引這些列的完整長(zhǎng)度)。

訣竅在于要選擇足夠長(zhǎng)的前綴以保證較高的選擇性,同時(shí)又不能太長(zhǎng)(以便節(jié)約空間)。前綴應(yīng)該足夠長(zhǎng),以使得前綴索引的選擇性接近于索引整個(gè)列。

SELECT COUNT(DISTINCT LEFT(order_note,3))/COUNT(*) AS sel3,
COUNT(DISTINCT LEFT(order_note,4))/COUNT(*)AS sel4,
COUNT(DISTINCT LEFT(order_note,5))/COUNT(*) AS sel5,
COUNT(DISTINCT LEFT(order_note, 6))/COUNT(*) As sel6,
COUNT(DISTINCT LEFT(order_note, 7))/COUNT(*) As sel7,
COUNT(DISTINCT LEFT(order_note, 8))/COUNT(*) As sel8,
COUNT(DISTINCT LEFT(order_note, 9))/COUNT(*) As sel9,
COUNT(DISTINCT LEFT(order_note, 10))/COUNT(*) As sel10,
COUNT(DISTINCT LEFT(order_note, 11))/COUNT(*) As sel11,
COUNT(DISTINCT LEFT(order_note, 12))/COUNT(*) As sel12,
COUNT(DISTINCT LEFT(order_note, 13))/COUNT(*) As sel13,
COUNT(DISTINCT LEFT(order_note, 14))/COUNT(*) As sel14,
COUNT(DISTINCT LEFT(order_note, 15))/COUNT(*) As sel15,
COUNT(DISTINCT order_note)/COUNT(*) As total
FROM order_exp;

8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化
可以看見(jiàn),從第10個(gè)開(kāi)始選擇性的增加值很高,隨著前綴字符的越來(lái)越多,選擇度也在不斷上升,但是增長(zhǎng)到第15時(shí),已經(jīng)和第14沒(méi)太大差別了,選擇性提升的幅度已經(jīng)很小了,都非常接近整個(gè)列的選擇性了。

那么針對(duì)這個(gè)字段做前綴索引的話(huà),從第13到第15都是不錯(cuò)的選擇,甚至第12也不是不能考慮。

在上面的示例中,已經(jīng)找到了合適的前綴長(zhǎng)度,如何創(chuàng)建前綴索引:
ALTER TABLE order_exp ADD KEY (order_note(14));
建立前綴索引后查詢(xún)語(yǔ)句并不需要更改:
select * from order_exp where order_note = ‘xxxx’ ;
前綴索引是一種能使索引更小、更快的有效辦法,但另一方面也有其缺點(diǎn)MySQL無(wú)法使用前綴索引做ORDER BY和GROUP BY,也無(wú)法使用前綴索引做覆蓋掃描。

有時(shí)候后綴索引 (suffix index)也有用途(例如,找到某個(gè)域名的所有電子郵件地址)。MySQL原生并不支持反向索引,但是可以把字符串反轉(zhuǎn)后存儲(chǔ),并基于此建立前綴索引。可以通過(guò)觸發(fā)器或者應(yīng)用程序自行處理來(lái)維護(hù)索引。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-445844.html

到了這里,關(guān)于8. 高性能業(yè)務(wù)表結(jié)構(gòu)設(shè)計(jì)和索引知識(shí)深化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • MySQL進(jìn)階篇:索引(概述,結(jié)構(gòu),分類(lèi),語(yǔ)法,SQL性能分析,索引使用,設(shè)計(jì)原則)

    MySQL進(jìn)階篇:索引(概述,結(jié)構(gòu),分類(lèi),語(yǔ)法,SQL性能分析,索引使用,設(shè)計(jì)原則)

    索引(index)是幫助MysQL 高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu) ( 有序 )。 在數(shù)據(jù)之外,數(shù)據(jù)庫(kù)系統(tǒng)還維護(hù)著滿(mǎn)足特定查找算法的數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)以某種方式引用(指向)數(shù)據(jù),這樣就可以在這些數(shù)據(jù)結(jié)構(gòu)上實(shí)現(xiàn)高級(jí)查找算法,這種數(shù)據(jù)結(jié)構(gòu)就是索引。 優(yōu)缺點(diǎn): MySQL的索引是在存儲(chǔ)

    2024年01月20日
    瀏覽(110)
  • ⑩② 【MySQL索引】詳解MySQL`索引`:結(jié)構(gòu)、分類(lèi)、性能分析、設(shè)計(jì)及使用規(guī)則。

    ⑩② 【MySQL索引】詳解MySQL`索引`:結(jié)構(gòu)、分類(lèi)、性能分析、設(shè)計(jì)及使用規(guī)則。

    個(gè)人簡(jiǎn)介:Java領(lǐng)域新星創(chuàng)作者;阿里云技術(shù)博主、星級(jí)博主、專(zhuān)家博主;正在Java學(xué)習(xí)的路上摸爬滾打,記錄學(xué)習(xí)的過(guò)程~ 個(gè)人主頁(yè):.29.的博客 學(xué)習(xí)社區(qū):進(jìn)去逛一逛~ 索引 : 什么是索引(index) ? 索引(index)是幫助MySQL 高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu) (有序):在數(shù)據(jù)之外,數(shù)據(jù)庫(kù)系統(tǒng)

    2024年02月05日
    瀏覽(25)
  • OpenResty安裝-(基于Nginx的高性能Web平臺(tái),可在Nginx端編碼業(yè)務(wù))

    OpenResty安裝-(基于Nginx的高性能Web平臺(tái),可在Nginx端編碼業(yè)務(wù))

    首先你的Linux虛擬機(jī)必須聯(lián)網(wǎng) 首先要安裝OpenResty的依賴(lài)開(kāi)發(fā)庫(kù),執(zhí)行命令: 你可以在你的 CentOS 系統(tǒng)中添加 openresty 倉(cāng)庫(kù),這樣就可以便于未來(lái)安裝或更新我們的軟件包(通過(guò) yum check-update 命令)。運(yùn)行下面的命令就可以添加我們的倉(cāng)庫(kù): 如果提示說(shuō)命令不存在,則運(yùn)行:

    2024年02月07日
    瀏覽(53)
  • 高性能MySQL實(shí)戰(zhàn)(一):表結(jié)構(gòu)

    最近因需求改動(dòng)新增了一些數(shù)據(jù)庫(kù)表,但是在定義表結(jié)構(gòu)時(shí),具體列屬性的選擇有些不知其所以然,索引的添加也有遺漏和不規(guī)范的地方,所以我打算為創(chuàng)建一個(gè)高性能表的過(guò)程以實(shí)戰(zhàn)的形式寫(xiě)一個(gè)專(zhuān)題,以此來(lái)學(xué)習(xí)和鞏固這些知識(shí)。 我使用的 MySQL 版本是 5.7,建表 DDL 語(yǔ)句

    2024年02月12日
    瀏覽(52)
  • 解析內(nèi)存中的高性能圖結(jié)構(gòu)

    在進(jìn)行各種圖處理、圖計(jì)算、圖查詢(xún)的時(shí)候,內(nèi)存或是硬盤(pán)中如何存儲(chǔ)圖結(jié)構(gòu)是一個(gè)影響性能的關(guān)鍵因素。本文主要分析了幾種常見(jiàn)的內(nèi)存圖結(jié)構(gòu),及其時(shí)間、空間復(fù)雜度,希望對(duì)你有所啟發(fā)。 通常來(lái)說(shuō),對(duì)于圖結(jié)構(gòu)的幾種常見(jiàn)的基礎(chǔ)操作: 插入一個(gè)點(diǎn) 插入一個(gè)邊 刪除一個(gè)

    2024年02月03日
    瀏覽(23)
  • Redis核心數(shù)據(jù)結(jié)構(gòu)實(shí)戰(zhàn)與高性能解析

    Redis核心數(shù)據(jù)結(jié)構(gòu)實(shí)戰(zhàn)與高性能解析

    目錄 一、安裝Redis 二、Redis線(xiàn)程與高性能 2.1 Redis是單線(xiàn)程么? 2.2 Redis讀寫(xiě)是單線(xiàn)程為何這么快? 2.3 Redis如何處理并發(fā)操作命令? 三、核心數(shù)據(jù)結(jié)構(gòu)實(shí)戰(zhàn) 3.1 字符串常用操作實(shí)戰(zhàn) SET 存入鍵值對(duì) SETNX SETEX MSET 批量存入鍵值對(duì) MSETNX DECR 原子減1 DECRBY 原子減 INCR 原子加1 INCRBY 原子

    2024年02月07日
    瀏覽(20)
  • 【分布式系統(tǒng)】聊聊高性能設(shè)計(jì)

    【分布式系統(tǒng)】聊聊高性能設(shè)計(jì)

    對(duì)于以上的數(shù)字,其實(shí)每個(gè)程序員都應(yīng)該了解,因?yàn)橹挥辛私膺@些基本的數(shù)字,才能知道對(duì)于CPU、內(nèi)存、磁盤(pán)、網(wǎng)絡(luò)之間數(shù)據(jù)讀寫(xiě)的時(shí)間。1000ms = 1S。毫秒-微秒-納秒-秒-分鐘 為什么高性能如此重要的呢,在架構(gòu)設(shè)計(jì)中,高性能、高可用、高并發(fā)是三高問(wèn)題。其實(shí)背后對(duì)應(yīng)的就

    2024年02月13日
    瀏覽(49)
  • 【架構(gòu)】后端服務(wù)架構(gòu)高性能設(shè)計(jì)方法

    【架構(gòu)】后端服務(wù)架構(gòu)高性能設(shè)計(jì)方法

    “N 高 N 可”,高性能、高并發(fā)、高可用、高可靠、可擴(kuò)展、可維護(hù)、可用性等是后臺(tái)開(kāi)發(fā)耳熟能詳?shù)脑~了,它們中有些詞在大部分情況下表達(dá)相近意思。本序列文章旨在探討和總結(jié)后臺(tái)架構(gòu)設(shè)計(jì)中常用的技術(shù)和方法,并歸納成一套方法論。 本文主要探討和總結(jié)服務(wù)架構(gòu)設(shè)計(jì)

    2024年02月11日
    瀏覽(25)
  • ElasticSearch_12_ES的高性能設(shè)計(jì)

    ElasticSearch_12_ES的高性能設(shè)計(jì)

    容量問(wèn)題: 電商網(wǎng)站商品上億條時(shí),涉及到單表數(shù)據(jù)過(guò)大必須拆分表,數(shù)據(jù)庫(kù)磁盤(pán)占用過(guò)大必須分庫(kù)(mycat)。 性能問(wèn)題: mysql實(shí)現(xiàn)模糊查詢(xún)必須使用 like, 只有 后模糊 才能走索引,前模糊和全模糊都不會(huì)走索引,比如查詢(xún)“筆記本電腦”等時(shí),上億條數(shù)據(jù)的商

    2024年02月02日
    瀏覽(20)
  • ZNS SSD 性能測(cè)試:解決傳統(tǒng)SSD問(wèn)題的高性能存儲(chǔ)棧設(shè)計(jì)

    聲明 主頁(yè) :元存儲(chǔ)的博客_CSDN博客 依公開(kāi)知識(shí)及經(jīng)驗(yàn)整理,如有誤請(qǐng)留言。 個(gè)人辛苦整理,付費(fèi)內(nèi)容, 禁止轉(zhuǎn)載 。 全文 3000 字, 內(nèi)容摘要 1 性能測(cè)試 1.1 環(huán)境搭建 1.2 原始設(shè)備的性能

    2023年04月17日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包