mysql 給現有資料做索引 mysql資料庫索引

2021-10-17 23:36:12 字數 2366 閱讀 5938

mysql索引實現

在mysql中,索引屬於儲存引擎級別的概念,不同儲存引擎對索引的實現方式是不同的,本文主要討論myisam和innodb兩個儲存引擎的索引實現方式。

走進搜尋引擎的作者梁斌老師針對b樹、b+樹給出了他的意見(為了真實性,特引用其原話,未作任何改動): 「b+樹還有乙個最大的好處,方便掃庫,b樹必須用中序遍歷的方法按序掃庫,而b+樹直接從葉子結點挨個掃一遍就完了,b+樹支援range-query非常方便,而b樹不支援。這是資料庫選用b+樹的最主要原因。

比如要查 5-10之間的,b+樹一把到5這個標記,再一把到10,然後串起來就行了,b樹就非常麻煩。b樹的好處,就是成功查詢特別有利,因為樹的高度總體要比b+樹矮。不成功的情況下,b樹也比b+樹稍稍佔一點點便宜。

b樹比如你的例子中查,17的話,一把就得到結果了,

有很多基於頻率的搜尋是選用b樹,越頻繁query的結點越往根上走,前提是需要對query做統計,而且要對key做一些變化。

另外b樹也好b+樹也好,根或者上面幾層因為被反覆query,所以這幾塊基本都在記憶體中,不會出現讀磁碟io,一般已啟動的時候,就會主動換入記憶體。"

這裡設表一共有三列,假設我們以col1為主鍵,上圖是乙個myisam表的主索引(primary key)示意。可以看出myisam的索引檔案僅僅儲存資料記錄的位址(預設是以儲存順序)。在myisam中,主索引和輔助索引(secondary key)在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重複。如果我們在col2上建立乙個輔助索引,則此索引的結構如下圖所示:

同樣也是一顆b+tree,data域儲存資料記錄的位址。因此,myisam中索引檢索的演算法為首先按照b+tree搜尋演算法搜尋索引,如果指定的key存在,則取出其data域的值,然後以data域的值為位址,讀取相應資料記錄。

myisam的索引方式也叫做「非聚集」的,之所以這麼稱呼是為了與innodb的聚集索引區分。

innodb索引實現

雖然innodb也使用b+tree作為索引結構,但具體實現方式卻與myisam截然不同。

第乙個重大區別是innodb的資料檔案本身就是索引檔案。從上文知道,myisam索引檔案和資料檔案是分離的,索引檔案僅儲存資料記錄的位址。而在innodb中,表資料檔案本身就是按b+tree組織的乙個索引結構,這棵樹的葉節點data域儲存了完整的資料記錄。這個索引的key是資料表的主鍵,因此innodb表資料檔案本身就是主索引。

上圖是innodb主索引(同時也是資料檔案)的示意圖,可以看到葉節點包含了完整的資料記錄。這種索引叫做聚集索引。因為innodb的資料檔案本身要按主鍵聚集,所以innodb要求表必須有主鍵(myisam可以沒有),如果沒有顯式指定,則mysql系統會自動選擇乙個可以唯一標識資料記錄的列作為主鍵,如果不存在這種列,則mysql自動為innodb表生成乙個隱含字段作為主鍵,這個字段長度為6個位元組,型別為長整形。

第二個與myisam索引的不同是innodb的輔助索引data域儲存相應記錄主鍵的值而不是位址。換句話說,innodb的所有輔助索引都引用主鍵作為data域。例如,上圖為定義在col3上的乙個輔助索引:

這裡以英文本元的ascii碼作為比較準則。聚集索引這種實現方式使得按主鍵的搜尋十分高效,但是輔助索引搜尋需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然後用主鍵到主索引中檢索獲得記錄。

了解不同儲存引擎的索引實現方式對於正確使用和優化索引都非常有幫助,例如知道了innodb的索引實現後,就很容易明白為什麼不建議使用過長的字段作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,用非單調的字段作為主鍵在innodb中不是個好主意,因為innodb資料檔案本身是一顆b+tree,非單調的主鍵會造成在插入新記錄時資料檔案為了維持b+tree的特性而頻繁的**調整,十分低效,而使用自增字段作為主鍵則是乙個很好的選擇。

使用explain對sql進行優化:

1) consts 單錶中最多只有乙個匹配行(主鍵或者唯一索引),在優化階段即可讀取到資料。

2) ref 指的是使用普通的索引。(normal index)

3) range 對索引進範圍檢索。

反例:explain 表的結果,type=index,索引物理檔案全掃瞄,速度非常慢,這個 index 級別

比較 range 還低,與全表掃瞄是小巫見大巫。

當使用索引時,innodb會鎖住它不需要的元組。更糟糕的是,如果查詢不能使用索引,mysql會進行全表掃瞄,並鎖住每乙個元組,不管是否真正需要

mysql給資料做排名 mysql給資料統計做排名

1 問題描述 目前有乙個表tb rank playerid,playername,score playerid是primary key 主鍵 現在的需求是,希望在表tb rank中再新增一列ranknum,這個ranknum記錄的是score的排名 根據分數做降序排列 2 初步解決方法 不考慮sco...

MYSQL資料庫基礎之如果給已有資料庫表修改字段

mysql資料庫是當下程式開發的主流資料庫,在原生程式的過程中當資料庫建立的資料庫表不能滿足實際開發需求,需要對已有的資料庫表裡面的字段進行修改操作,這裡就不過多的進行詳細說明,只是對相關資料表字段調整的sql語句進行乙個歸納整理 修改欄位名稱 alter table 表名 change 原表名 新...

mysql給資料量大的表新增索引的辦法

有乙個問題,一張表有3百萬條記錄,隨著時間的增加,記錄量會更多,此時查詢速度很慢。在建立此表前沒有未相應字段新增索引,所以此時需要為表新增索引。但是因為資料量大的原因,索引新增不成功,想了很多辦法,終於在短時間內解決了。辦法如下 1 進入mysql介面。mysql uroot hlocalhost ...