亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

MySQL怎么給字符串字段加索引

 更新時(shí)間:2022年03月06日 08:39:44   作者:Love&Share  
本文主要介紹了MySQL怎么給字符串字段加索引,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

假設(shè),你現(xiàn)在維護(hù)一個(gè)支持郵箱登錄的系統(tǒng),用戶表是這么定義的:

create table SUser(
?ID bigint unsigned primary key,
?email varchar(64), 
?... 
?)engine=innodb;

由于要使用郵箱登錄,所以業(yè)務(wù)代碼中一定會(huì)出現(xiàn)類似于這樣的語(yǔ)句:

select f1, f2 from SUser where email='xxx';

如果 email 這個(gè)字段上沒(méi)有索引,那么這個(gè)語(yǔ)句就只能做全表掃描。

1)那我可以在郵箱地址這個(gè)字段上面建索引嗎?

  • MySQL 是支持前綴索引的,可以定義字符串的一部分作為索引

2)如果創(chuàng)建索引的語(yǔ)句不指定前綴長(zhǎng)度,那么會(huì)怎么樣?

  • 索引就會(huì)包含整個(gè)字符串

3)能舉例來(lái)說(shuō)明一下嗎?

alter table SUser add index index1(email);
?或
?alter table SUser add index index2(email(6));
  • index1 索引里面,包含了每個(gè)記錄的整個(gè)字符串

  • index2 索引里面,對(duì)于每個(gè)記錄都是只取前 6 個(gè)字節(jié)

4)這兩種不同的定義在數(shù)據(jù)結(jié)構(gòu)和存儲(chǔ)上有什么區(qū)別呢?

明顯看出email(6) 這個(gè)索引結(jié)構(gòu)占用的空間會(huì)更小

5)email(6) 這個(gè)索引結(jié)構(gòu)有什么缺點(diǎn)嗎?

  • 可能會(huì)增加額外的記錄掃描次數(shù)

6)下面這個(gè)語(yǔ)句,在這兩個(gè)索引定義下分別是怎么執(zhí)行的?

select id,name,email from SUser where email='zhangssxyz@xxx.com';

index1(即 email 整個(gè)字符串的索引結(jié)構(gòu)),執(zhí)行順序

  • 從 index1 索引樹(shù)找到滿足索引值是’zhangssxyz@xxx.com’的這條記錄,取得 ID2 的值;

  • 回表查到主鍵值是 ID2 的行,判斷 email 的值是正確的,將這行記錄加入結(jié)果集;

  • 繼續(xù)在index索引樹(shù)的下一條記錄,發(fā)現(xiàn)已經(jīng)不滿足 email='zhangssxyz@xxx.com’的條件了,循環(huán)結(jié)束。

這個(gè)過(guò)程中,只需要回主鍵索引取一次數(shù)據(jù),所以系統(tǒng)認(rèn)為只掃描了一行。

index2(即 email(6) 索引結(jié)構(gòu)),執(zhí)行順序

  • 從 index2 索引樹(shù)找到滿足索引值是’zhangs’的記錄,找到的第一個(gè)是 ID1;

  • 到主鍵上查到主鍵值是 ID1 的行,判斷出 email 的值不是’zhangssxyz@xxx.com’,這行記錄丟棄;

  • 取 index2 上剛剛查到的位置的下一條記錄,發(fā)現(xiàn)仍然是’zhangs’,取出 ID2,再到 ID 索引上取整行然后判斷,這次值對(duì)了,將這行記錄加入結(jié)果集;

  • 重復(fù)上一步,直到在 idxe2 上取到的值不是’zhangs’時(shí),循環(huán)結(jié)束。

在這個(gè)過(guò)程中,要回主鍵索引取 4 次數(shù)據(jù),也就是掃描了 4 行。

7)通過(guò)上面的對(duì)比,能得出什么結(jié)論?

  • 使用前綴索引后,可能會(huì)導(dǎo)致查詢語(yǔ)句讀數(shù)據(jù)的次數(shù)變多。

8)前綴索引真的一無(wú)是處嗎?

  • 如果我們定義的 index2 不是 email(6) 而是 email(7),那滿足前綴’zhangss’的記錄只有一個(gè),直接就查到 ID2了,只掃描一行就結(jié)束了。

9)那么使用前綴索引有哪些注意事項(xiàng)?

  • 長(zhǎng)度選擇合理

10)當(dāng)要給字符串創(chuàng)建前綴索引時(shí),我咋知道我該用多長(zhǎng)的前綴索引呢?

  • 統(tǒng)計(jì)索引上有多少個(gè)不同的值來(lái)判斷要使用多長(zhǎng)的前綴。

11)怎樣統(tǒng)計(jì)索引上有多少個(gè)不同的值?

select count(distinct email) as L from SUser;

12)拿到了索引對(duì)應(yīng)的有多少個(gè)不同的值之后下一步該做什么?

  • 依次選取不同長(zhǎng)度的前綴來(lái)看這個(gè)值

    select 
    ? ?count(distinct left(email,4))as L4,
    ? ?count(distinct left(email,5))as L5,
    ? ?count(distinct left(email,6))as L6,
    ? ?count(distinct left(email,7))as L7,
    ?from SUser;
  • 然后,在 L4~L7 中,找出第一個(gè)不小于 L * 95% 的值,說(shuō)明通過(guò)這個(gè)索引可以找出百分之95以上的數(shù)據(jù)。

13)前綴索引對(duì)覆蓋索引的影響是什么?

下面這個(gè) SQL 語(yǔ)句:

select id,email from SUser where email='zhangssxyz@xxx.com';

與前面例子中的 SQL 語(yǔ)句

select id,name,email from SUser where email='zhangssxyz@xxx.com';

相比,第一個(gè)語(yǔ)句只要求返回 id 和 email 字段。

  • 如果使用 index1(即 email 整個(gè)字符串的索引結(jié)構(gòu))的話,查email的話就能得到ID,那就不用回表了,這個(gè)就是覆蓋索引。

  • 用 index2(即 email(6) 索引結(jié)構(gòu))的話,就不得不回到 ID 索引再去判斷 email 字段的值。

14)那我把index2 的定義修改為 email(18) 的前綴索引不就行了?

  • 這個(gè)18是你自己定義的,系統(tǒng)不知道18這個(gè)長(zhǎng)度是否已經(jīng)大于我的email長(zhǎng)度,所以它還是會(huì)回表去查一下驗(yàn)證。

總而言之:使用前綴索引就用不上覆蓋索引對(duì)查詢性能的優(yōu)化了

15)對(duì)于類似于郵箱這樣的字段來(lái)說(shuō),使用前綴索引的效果可能還不錯(cuò)。但是,遇到身份證這種前綴的區(qū)分度不夠好的情況時(shí),我們要怎么辦呢?

  • 索引選取的要更長(zhǎng)一些。

    • 但是所以越長(zhǎng)的話,占的磁盤空間更大,相同的一頁(yè)能放下的索引值就變少了,反而會(huì)影響查詢效率。

16)如果我們能夠確定業(yè)務(wù)需求里面只有按照身份證進(jìn)行等值查詢的需求,還有沒(méi)有別的處理方法呢?

  • 既然正過(guò)來(lái)相同的多,那我就把它倒過(guò)來(lái)存。查詢時(shí)候這樣查

    select field_list from t where id_card = reverse('input_id_card_string');

    使用 的時(shí)候用count(distinct) 方法去做個(gè)驗(yàn)證

  • 使用 hash 字段。在表上再創(chuàng)建一個(gè)整數(shù)字段,來(lái)保存身份證的校驗(yàn)碼,同時(shí)在這個(gè)字段上創(chuàng)建索引。

    alter table t add id_card_crc int unsigned, add index(id_card_crc);

    每次插入新記錄的時(shí)候,都同時(shí)用 crc32() 這個(gè)函數(shù)得到校驗(yàn)碼填到這個(gè)新字段。由于校驗(yàn)碼可能存在沖突,也就是說(shuō)兩個(gè)不同的身份證號(hào)通過(guò) crc32() 函數(shù)得到的結(jié)果可能是相同的,所以你的查詢語(yǔ)句 where 部分要判斷 id_card 的值是否精確相同。

    select field_list from t where id_card_crc=crc32('input_id_card_string') and id_card='input_id_card_string'

    這樣,索引的長(zhǎng)度變成了 4 個(gè)字節(jié)(int類型),比原來(lái)小了很多

17)使用倒序存儲(chǔ)和使用 hash 字段這兩種方法有什么異同點(diǎn)?

  • 相同點(diǎn):都不支持范圍查詢

    • 倒序存儲(chǔ)的字段上創(chuàng)建的索引是按照倒序字符串的方式排序的,已經(jīng)沒(méi)有辦法利用索引方式查出身份證號(hào)碼在[ID_X, ID_Y]的所有市民了。同樣地,hash 字段的方式也只能支持等值查詢。

  • 區(qū)別

    • 從占用的額外空間來(lái)看,倒序存儲(chǔ)方式在主鍵索引上,不會(huì)消耗額外的存儲(chǔ)空間,而 hash 字段方法需要增加一個(gè)字段。當(dāng)然,倒序存儲(chǔ)方式使用 4 個(gè)字節(jié)的前綴長(zhǎng)度應(yīng)該是不夠的,如果再長(zhǎng)一點(diǎn),這個(gè)消耗跟額外這個(gè) hash 字段也差不多抵消了。

    • 在 CPU 消耗方面,倒序方式每次寫和讀的時(shí)候,都需要額外調(diào)用一次 reverse 函數(shù),而 hash 字段的方式需要額外調(diào)用一次 crc32() 函數(shù)。如果只從這兩個(gè)函數(shù)的計(jì)算復(fù)雜度來(lái)看的話,reverse 函數(shù)額外消耗的 CPU 資源會(huì)更小些。

    • 從查詢效率上看,使用 hash 字段方式的查詢性能相對(duì)更穩(wěn)定一些。因?yàn)?crc32 算出來(lái)的值雖然有沖突的概率,但是概率非常小,可以認(rèn)為每次查詢的平均掃描行數(shù)接近 1。而倒序存儲(chǔ)方式畢竟還是用的前綴索引的方式,也就是說(shuō)還是會(huì)增加掃描行數(shù)。

案例:如果你在維護(hù)一個(gè)學(xué)校的學(xué)生信息數(shù)據(jù)庫(kù),學(xué)生登錄名的統(tǒng)一格式是”學(xué)號(hào) @gmail.com", 而學(xué)號(hào)的規(guī)則是:十五位的數(shù)字,其中前三位是所在城市編號(hào)、第四到第六位是學(xué)校編號(hào)、第七位到第十位是入學(xué)年份、最后五位是順序編號(hào)。

18)系統(tǒng)登錄的時(shí)候都需要學(xué)生輸入登錄名和密碼,驗(yàn)證正確后才能繼續(xù)使用系統(tǒng)。就只考慮登錄驗(yàn)證這個(gè)行為的話,你會(huì)怎么設(shè)計(jì)這個(gè)登錄名的索引呢?

  • 一個(gè)學(xué)校每年預(yù)估2萬(wàn)新生,50年才100萬(wàn)記錄,能節(jié)省多少空間,直接全字段索引。省去了開(kāi)發(fā)轉(zhuǎn)換及局限性風(fēng)險(xiǎn),碰到超大量迫不得已再用后兩種辦法

  • 實(shí)際操作上直接全字段索引就行了,一個(gè)學(xué)校數(shù)據(jù)庫(kù)的數(shù)據(jù)量和查詢壓力都不會(huì)大到哪兒去。 如果單從優(yōu)化數(shù)據(jù)表的角度: \1. 后綴@gmail可以單獨(dú)一個(gè)字段來(lái)存,或者用業(yè)務(wù)代碼來(lái)保證, \2. 城市編號(hào)和學(xué)校編號(hào)估計(jì)也不會(huì)變,也可以用業(yè)務(wù)代碼來(lái)配置 \3. 然后直接存年份和順序編號(hào)就行了,這個(gè)字段可以全字段索引

 到此這篇關(guān)于MySQL怎么給字符串字段加索引的文章就介紹到這了,更多相關(guān)MySQL字符串字段加索引內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Navicat連接MySQL提示1045錯(cuò)誤解決(重置MySQL密碼)

    Navicat連接MySQL提示1045錯(cuò)誤解決(重置MySQL密碼)

    連接MySQL數(shù)據(jù)庫(kù)時(shí)難免會(huì)遇到1045錯(cuò)誤,主要是因?yàn)橛脩糨斎氲挠脩裘蛎艽a錯(cuò)誤被拒絕訪問(wèn),如果不想重裝,需要找回密碼或者重置密碼,這篇文章主要給大家介紹了關(guān)于Navicat連接MySQL提示1045錯(cuò)誤解決的方法,主要是重置MySQL密碼,需要的朋友可以參考下
    2023-04-04
  • MySQL5.7安裝過(guò)程并重置root密碼的方法(shell 腳本)

    MySQL5.7安裝過(guò)程并重置root密碼的方法(shell 腳本)

    由于 MySQL 5.7 版本的 root 密碼是首次啟動(dòng)時(shí)隨機(jī)生成的,并且還要求必須修改后才能使用。下面小編給大家分享使用shell 腳本完成安裝和設(shè)置新的 root 密碼的方法,一起看看吧
    2016-12-12
  • 最新評(píng)論