阿里百度華為如何使用MySQL給字串加索引

2021-10-08 13:04:26 字數 4612 閱讀 8964

現在主流**都支援手機號登入,如何在手機號這樣的字串字段建立合適的索引呢?

假設,你現在維護乙個支援郵箱登入的系統,使用者表是這麼定義的:

create

table suser(

id bigint

unsigned

primary

key,

email varchar(64

),..

.)engine

=innodb

;

要使用郵箱登入,會有語句:

select f1, f2 from suser where email=

'***'

;

若email欄位無索引,該語句只能全表掃瞄。

mysql支援字首索引,可定義字串的一部分作為索引。

若建立索引的語句不指定字首長度,那麼索引預設包含整個字串。

比如,這倆在email欄位建立索引的語句:

alter

table suser add

index index1(email)

;alter

table suser add

index index2(email(6)

);

可見,email(6)索引結構中每個郵箱欄位都只取前6位元組(zhangs),占用空間更小,這就是字首索引優勢。

這同時帶來損失:可能會增加額外的記錄掃瞄次數。

看看下面這語句,在這倆索引定義分別怎麼執行。

select id,name,email from suser where email=

'zhangssxyz@***.com'

;

如果使用index1,執行順序如下:

從index1索引樹找到滿足索引值 'zhangssxyz@***.com』的記錄,取得id2的值

到主鍵上查到主鍵值是id2的行,判斷email值是正確的,將改行記錄加入結果集

取index1索引樹上剛剛查到位置的下條記錄,發現已不滿足email='zhangssxyz@***.com』條件,結束迴圈

該過程,只需回主鍵索引取一次資料,所以系統認為只掃瞄一行。

如果使用是index2,執行順序如下:

從index2索引樹找到滿足索引值是』zhangs』的記錄,找到的第乙個是id1

到主鍵上查到主鍵值是id1的行,判斷出email的值不是』zhangssxyz@***.com』,該行記錄丟棄

取index2上剛剛查到的位置的下條記錄,仍是』zhangs』,取出id2,再到id索引取整行判斷,這次值對,將該行記錄加入結果集

重複上一步,直到在idxe2上取值不是』zhangs』,結束迴圈結束

該過程,要回主鍵索引取4次資料,即掃瞄4行。

對比發現,使用字首索引,可能導致查詢語句讀資料的次數變多。

但對該查詢語句,如果定義index2不是email(6)而是email(7),即取email欄位前7位元組構建索引,即滿足字首』zhangss』記錄只有乙個,也能直接查到id2,只掃瞄一行結束。

即使用字首索引,定義好長度,就可做到既節省空間,又不用增加額外太多的查詢成本。

要給字串建立字首索引

在建立索引時我們關注的是區分度,區分度越高越好。區分度越高,重複的鍵值越少。因此可通過統計索引上有多少不同值判斷要使用多長字首。

可使用如下語句,計算該列上有多少不同值

select

count

(distinct email)

as l from suser;

依次選取不同長度字首來測該值,比如看4~7個位元組字首索引:

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;

使用字首索引可能會損失區分度,所以需要預先設定乙個可接受損失比例,比如5%。

然後,在返回的l4~l7中,找出不小於 l * 95%的值,假設l6、l7都滿足時,即可選擇字首長度最短為6。

看如下sql:

select id,email from suser where email=

'zhangssxyz@***.com'

;

與前例sql語句:

select id,name,email from suser where email=

'zhangssxyz@***.com'

;

相比,該語句只要求返回id和email。

若使用index1,可利用覆蓋索引,從index1查到結果後直接返回,不需回到id索引再查一次。

而若使用index2(email(6)),得回id索引再判斷email字段值。

即使將index2定義改為email(18),雖然index2已包含所有資訊,但innodb還是要回id索引再查,因為系統並不確定字首索引的定義是否截斷了完整資訊。

即字首索引根本用不上覆蓋索引對查詢的優化,這也是選擇是否使用字首索引時需要考慮的因素。

對類似郵箱這樣字段,字首索引可能還行。但遇到字首區分度不好的,怎麼辦?

比如身份證號18位,前6位是位址碼,所以同縣人身份證號前6位一般相同。

假設維護資料庫是個市公民資訊系統,若對身份證號做長度6字首索引,區分度非常低。

可能需建立長度12以上字首索引,才能夠滿足區分度要求。

索引選取越長,佔磁碟空間越大,相同資料頁能放下索引值越少,查詢效率就越低。

第一種方式使用

如果儲存身份證號時把它倒過來存,每次查詢這麼寫:

select field_list from t where id_card = reverse(

'input_id_card_string'

);

由於身份證號最後6位沒有位址碼這樣重複邏輯,所以最後6位可能提供足夠的區分度。

實踐中也別忘記使用count(distinct)驗證區分度哦!

第二種方式是使用

可在表再建立整數字段,儲存身份證的校驗碼,同時在該字段建立索引。

alter

table t add id_card_crc int

unsigned

,add

index

(id_card_crc)

;

每次插新記錄時,同時用crc32()函式得到校驗碼填到該新字段。

由於校驗碼可能存在衝突,即兩不同身份證號crc32()所得結果可能相同(雜湊衝突),所以查詢語句where部分要判斷id_card值是否精確相同。

select field_list from t where 

id_card_crc=crc32(

'input_id_card_string'

)and id_card=

'input_id_card_string'

這索引長度變4位元組,比原來小很多。

都不支援範圍查詢。

占用的額外空間

cpu消耗

若只從這倆函式計算複雜度看,reverse函式額外消耗cpu資源較少。

查詢效率

字串字段建立索引的場景,可使用的方式如下:

直接建立完整索引,這樣可能比較占用空間

建立字首索引,節省空間,但增加查詢掃瞄次數,且不能使用覆蓋索引

倒序儲存,再建立字首索引,用於繞過字串本身字首的區分度不足缺陷

建立hash欄位索引,查詢效能穩定,有額外儲存和計算消耗,跟第三種方式一樣不支援範圍掃瞄

實際應用中,根據業務欄位的特點擊擇使用哪種方式。

維護學生資訊資料庫,學生登入名的統一格式是」學號@gmail.com"

學號的則是:十五位的數字,其中前三位是所在城市編號、第四到第六位是學校編號、第七位到第十位是入學年份、最後五位是順序編號。

系統登入時輸入登入名和密碼,驗證正確後才能繼續使用系統。

只考慮登入驗證,怎麼設計這個登入名的索引呢?

上期我留給你的問題是,給乙個學號字段建立索引,有哪些方法。

由於學號規則,無論正向反向字首索引,重複度都較高。

因為維護的只是乙個學校的,因此前面6位(其中,前三位是所在城市編號、第四到第六位是學校編號)固定,郵箱字尾都是@gamil.com,因此可只存入學年份加順序編號,長度9位。

在此基礎,可用數字型存這9位數字。比如201100001,只需佔4位元組。其實這就是種hash,只是用最簡單轉換規則:字串轉數字,而剛好我們設定背景,可保證轉換結果唯一。

當然了,乙個學校的總人數這種資料量,50年才100萬學生,這錶肯定是小表。為了業務簡單,直接存原來的字串。「優化成本和收益」的思想。

阿里做題 百度做題

阿里大概題目兩個單元 1 單選。大部分數學邏輯題 小部分程式設計基礎題 選擇題目 strlen和sizeof的用法 幾乎逢考必見 資料結構樹的遍歷,和equal的區別 排序的複雜度分析 程式設計題目 1 考察hadoop檔案讀寫過程 2 編寫乙個轉賬介面,注意條件 餘額 轉賬金額 轉賬次數 1000...

阿里雲 騰訊雲 百度雲 華為雲 評測對比

所有伺服器測試使用的軟體版本均為 vps bench v0.3.2 版本 源 在 github 您可以在這裡檢視原始資料以及 您可以在這裡看每次單獨的測試結果 從結果上看,這四家的cpu計算穩定性都不差,畢竟都是有雄厚技術支援的廠家。具體結果如下圖所示 註解 國內的網路這四家看來差不多 實際上網路還...

百度的搜尋工具如何使用

在使用搜尋引擎搜尋時大家都有注意到,搜尋欄下面有個 搜尋工具 這是為了方便進行更加詳細搜尋!那麼,搜尋工具該如何使用呢?點開搜尋工具我們能看到有一欄時間選項。你可以在這裡選擇你需要的檔案發布的具體時間。第二欄是檔案型別,你可以根據需要選擇型別,如word。第三欄是選擇輸入 進行站內搜尋!下面以 河南...