Mysql性能優化:如何給字符串加索引?

2020-12-14 計算機java編程

前綴索引

顧名思義,對於列值較長,比如BLOB、TEXT、VARCHAR,就 "必須" 使用前綴索引,即將值的前一部分作為索引。因為索引的存儲也是需要空間的,同樣索引太長維護起來也比較困難。比如我們給User表中的郵箱添加前綴索引,如下: alter table user add index index1(email(7));

上述語句將email的前7個字符作為索引。前綴索引和普通索引比較

我們分別將email的全部作為索引和前7個字符作為索引來看看在性能上有什麼差異。建立索引的語句如下: alter table user add index index1(email);

alter table user add index index2(email(7));

假設有user表中有這樣幾條數據(id,name,email):(1,"陳某","chenmou1993@xxx")、(2,"張某","chenmou1994@xxx")、(3,"李某","chenmou1995@xxx")、(4,"王某","chenmou1996@xxx")。對應於index1和index2的索引樹如下兩張圖:

如果執行下面的查詢語句,Mysql如何利用索引來查詢呢?  select * from user where email="chenmou1995@xxx";

【1】普通索引的執行過程

從index1索引樹找到滿足索引值是chenmou1995@xxx的這條記錄,取得id=2的值;到主鍵上查到主鍵值是id=2的行,判斷email的值是正確的,將這行記錄加入結果集;取index1索引樹上剛剛查到的位置的下一條記錄,發現已經不滿足email=chenmou1995@xxx的條件了,循環結束。這個過程中,只需要回主鍵索引取一次數據,所以系統認為只掃描了一行

【2】前綴索引的執行過程

從index2索引樹找到滿足索引值是chenmou的記錄,找到的第一個是id=1;到主鍵上查到主鍵值是id=1的行,判斷出email的值不是chenmou1995@xxx,這行記錄丟棄;取index2上剛剛查到的位置的下一條記錄,發現仍然是chenmou,取出id=2,再到ID索引上取整行然後判斷,這次值對了,將這行記錄加入結果集;重複上一步,直到在idxe2上取到的值不是chenmou時,循環結束。在這個過程中,要回主鍵索引取4次數據,也就是掃描了4行。

通過以上查詢的對比,很容易就可以發現,使用前綴索引後,可能會導致查詢語句讀數據的次數變多。但是對於這個查詢語句來說,如果建立的前綴索引的長度為13呢?那麼滿足chenmou1995的記錄只有一個,這樣就可以直接定位到id=2,此時不但空間縮小了,掃描的行數也減少了。於是結論就來了:使用前綴索引,只要定義好長度,就可以做到既節省空間,又不用額外增加太多的查詢成本。那麼如何建立正確的前綴索引才能達到最佳的性能呢?接著往下看................如何建立最佳性能的前綴索引

通過上述的比較,可以得出一個結論,建立前綴索引的區分度越高越好,意味著重複的鍵值越少那麼如何統計區分度,其實很簡單,只需要判斷資料庫中重複的次數即可。sql如下:  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 user;

但是如果對於使用前綴區分度不太好的情況,比如,我們國家的身份證號,一共18位,其中前6位是地址碼,所以同一個縣的人的身份證號前6位一般會是相同的。 這時候如果對身份證號做長度為6的前綴索引的話,這個索引的區分度就非常低了。按照我們前面說的方法,可能你需要創建長度為12以上的前綴索引,才能夠滿足區分度要求。但是,索引選取的越長,佔用的磁碟空間就越大,相同的數據頁能放下的索引值就越少,搜索的效率也就會越低。那麼,如果我們能夠確定業務需求裡面只有按照身份證進行等值查詢的需求,還有沒有別的處理方法呢?這種方法,既可以佔用更小的空間,也能達到相同的查詢效率。現在簡單的介紹一種解決此種問題的方式,當然方法肯定不止一種,如下:倒序存儲

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

select field_list from t where id_card = reverse('輸入的身份證號');

由於身份證號的最後6位沒有地址碼這樣的重複邏輯,所以最後這6位很可能就提供了足夠的區分度。當然了,實踐中你不要忘記使用count(distinct)方法去做個驗證。

前綴索引對覆蓋索引的影響

前綴索引會導致覆蓋索引失效,查詢語句如下:select id,name from user where email="chenmou1995@xxx";由於使用了前綴索引,因此必須會回表驗證查詢到的時候正確,此處使用了覆蓋索引也是無效的。也就是說,使用前綴索引就用不上覆蓋索引對查詢性能的優化了,這也是你在選擇是否使用前綴索引時需要考慮的一個因素。總結

如何給字符串加索引是一個需要考量的問題,陳某在這裡給出如下的建議:

如果字符串長度很短,建議直接用全部作為索引。使用前綴索引注意分析區分度,區分度越高越好。使用前綴索引需要考慮覆蓋索引失效的問題。

相關焦點

  • 聊完了mysql索引,面試官直接給我漲了2000!
    # 前言mysql索引真的是一個讓人不得不說的話題,這個東西你在面試中會用到,在實際的工作中也會用到,這更是一個專業的DBA所必須掌握的內容,它的重要性體你在大廠的面試題匯總也可以看到,屬於必問的一個內容。
  • mysql實現php函數explode功能mysql_explode
    table temp_keys(id int(10) primary key auto_increment,keystr varchar(255));新建一個自定義函數mysql_explodeinsert into temp_keys values(null,'萬劍歸宗');insert into temp_keys values(null,'傲寒六決');自定義函數如下:drop functionif exists mysql_explode
  • 女朋友都能看懂的,SQL優化乾貨
    一、什麼情況會不走索引1、模糊查詢,在欄位開頭模糊select * from teacher where name like '%老師'優化:在欄位後面使用模糊查詢select * from teacher where name like '李%'如果一定要在欄位開頭模糊查詢,那可以使用INSTR(str,substr)意思是:在字符串str裡面,字符串substr出現的第一個位置(index),index
  • 9位阿里大牛發布這份800多頁MySQL性能優化法則筆記
    :本章能夠幫助大家加深對MySQL中索引和Join算法的理解,可以結合本書中的執行計劃和案例章節來閱讀本章內容。本章最後將介紹DBA在性能優化、測試和比較時需要關注的性能指標。第24章歷史問題診斷和現場故障分析:本章主要介紹如何去分析、診斷問題,以及如何重現問題,讓問題可追根溯源。
  • Python3.9官方文檔翻譯版python簡介之字符串
    ,你可以在第一個字母前加」r」標註字符串String literals can span multiple lines.There is no separate character type; a character is simply a string of size one:自譯:字符串可以被索引(下標)。起始索引位置為0、並沒有單獨的字符串文字類型;一個字符串文字只是長度為1的字符串文字。
  • 從原理到優化,深入淺出資料庫索引 - 計算機java編程
    而且,只有MyISAM 儲存引擎支持全文索引。(4)創建單列索引這裡需要注意的,subject 的長度為255,但是index4_st索引只有10。這樣做的目的還是為了提高查詢速度。對於字符型的數據,可以不用查詢全部信息,只查詢其前面的若干字符信息。
  • Mysql常用關鍵字指令和參數總結
    最近在學習極客時間上的mysql課程,對mysql資料庫有了更多了解,本篇文章是想總結一些mysql的基礎知識。目的是加深自己的記憶,也可以提升對mysql設計原理的了解。讀提交隔離級別的優勢:語句執行過程中加的行鎖,在語句執行完成後就把不滿足條件的鎖釋放了,不用等到事務提交,比可重複度和串行化更快。
  • 後端接口訪問數據查詢如何提高性能?從MySQL、ES、HBASE等技術出發...
    隱式字符編碼轉換在連表查詢時倒可能出現,即連表欄位的類型相同但字符編碼不同。破壞了有序性至於 Like 語句 % 開頭、字符串未加 』』 原因基本一致,MySQL 認為對索引欄位的操作可能會破壞索引有序性就機智的優化掉了。
  • Mysql資料庫部分
    在筆試題最後一般都是有一道關於mysql語句的問題,讓手寫出增、刪、改、查語句,今天我們就學習一下mysql語句。2.索引問題在做性能跟蹤分析過程中,經常發現有不少後臺程序的性能問題是因為缺少合適索引造成的,有些表甚至一個索引都沒有。這種情況往往都是因為在設計表時,沒去定義索引,而開發初期,由於表記錄很少,索引創建與否,可能對性能沒啥影響,開發人員因此也未多加重視。然一旦程序發布到生產環境,隨著時間的推移,表記錄越來越多。
  • MySQL count(*),count(1),count(field)區別、性能差異及優化建議
    count(id) 雖然也走二級索引(k_1),但是性能明顯低於count(*)和count(1),可能MySQL內部在處理count(*)和count(1)時做了額外的優化。強制走主鍵索引時,性能反而沒有走更小的二級索引好,InnoDB存儲引擎是索引組織表,行數據在主鍵索引的葉子節點上,走主鍵索引掃描時,處理的數據量比二級索引更多,所以性能不及二級索引。
  • 您的包裹「 MySQL靈魂十連」 待籤收
    從節點開啟一個線程(I/O Thread)把自己扮演成 mysql 的客戶端,通過 mysql 協議,請求主節點的二進位日誌文件中的事件 。還可以延伸到由於主從配置不一樣、主庫大事務、從庫壓力過大、網絡震蕩等造成主備延遲,如何避免這個問題?主備切換的時候用可靠性優先原則還是可用性優先原則?如何判斷主庫Crash了?互為主備情況下如何避免主備循環複製?被刪庫跑路了如何正確恢復?(⊙o⊙)… 感覺越來越扯到 DBA 的活兒上去了。
  • MySQL怎麼按指定字符合併及拆分 詳細實例分析
    按照指定字符進行合併或拆分是經常碰到的場景,MySQL在合併的寫法上比較簡單,但是按指定字符拆分相對比較麻煩一點(也就是要多寫一些字符)。本文將舉例演示如何進行按照指定字符合併及拆分。
  • Loadrunner測試mysql資料庫
    loadrunner可以利用mysql lib庫,通過引用外部DLL,模擬mysql客戶端連接資料庫進行增刪改查的操作進行測試。下面主要介紹如何利用mysql lib庫連接mysql資料庫進行性能測試。一、準備工作1.
  • 小心避坑:MySQL分頁時使用 limit+order by 會出現數據重複問題
    2、分析問題在MySQL 5.6的版本上,優化器在遇到order by limit語句的時候,做了一個優化,即 使用了priority queue。MySQL 5.5 沒有這個優化,所以也就不會出現這個問題。也就是說,MySQL 5.5是不存在本文提到的問題的,5.6版本之後才出現了這種情況。
  • 10個很棒的 JavaScript 字符串技巧
    我們稱一個字符序列為字符串。這幾乎是所有程式語言中都有的基本類型之一。這裡跟大家展示關於 JS 字符串的10個很棒的技巧,你可能還不知道哦?1.如何多次複製一個字符串JS 字符串允許簡單的重複,與純手工複製字符串不同,我們可以使用字符串的repeat方法。2. 如何填充一個字符串到指定的長度有時,我們希望字符串具有特定長度。
  • Mysql性能優化:為什麼你的count(*)這麼慢?
    如何提升count效率在InnoDB對於如何提升count(*)的查詢效率,網上有多種解決辦法,這裡主要介紹三種,並分析可行性。如何使用呢?很簡單,直接將計數保存在一張表中(table_name,total)。
  • 漫畫:什麼是字符串匹配算法?
    為了統一概念,在後文中,我們把字符串A稱為主串,把字符串B稱為模式串。第二輪,我們把模式串後移一位,從主串的第二位開始,把主串和模式串的字符逐個比較:主串的第二位字符是b,模式串的第二位字符也是b,兩者匹配,繼續比較:主串的第三位字符是b,模式串的第三位字符也是c,兩者並不匹配。
  • 請確保你查詢mysql資料庫時,sql語句沒有這麼寫
    資料庫索引,可以讓查詢sql語句效率更高。所以大家在寫查詢的sql語句時為了讓語句執行效率高會讓語句能命中索引,或者新建合適的索引。可是,有時候大家會遇到像下面說的這樣的情況。明明我sql語句where條件的欄位是符合索引,應該可以命中索引的,但是執行時卻沒有命中索引。為什麼會這樣呢,是人性的……額,串臺了,調回來。要說明這個問題,大家先來比較一下下面的這兩個sql語句。
  • 基於Canal和Kafka實現MySQL的Binlog近實時同步
    這篇文章簡單介紹一下如何快速地搭建一套Canal相關的組件。關於Canal簡介下面的簡介和下一節的原理均來自於Canal項目的README:Canal[kə'næl],譯意為水道/管道/溝渠,主要用途是基於MySQL資料庫增量日誌解析,提供增量數據訂閱和消費。