mysql innodb存儲與索引的總結

          Innodb存儲

          表空間是邏輯存放所有數據的地方,默認情況下會共享一個表空間——ibdata1,但如果把innodb_file_per_table=ON后每張表可以單獨放到一個表空間內,但還是有很多數據保存在共享的表ibdata1中,如undo信息等。

           

          表空間由各種段(segment)組成,常見的段有數據段、索引段等。Innodb是索引組織的,數據段就是clustered index的葉結點。需要注意的是,不是每個對象都有段。

           

          (extend)是由64個連續的頁組成,每個頁(page)固定為16KB,所以每個區總共為1M。頁是innodb最小的磁盤管理單位。

           

          Innodb是按行進行存放的,每個區最少可以保存2條記錄,否則就成鏈式結構了。每行數據除了自定義列以外,還會增加事務id和回滾指針列。如果沒有定義primary key也沒有not nullunique,則會增加6字節的RowId列作為主鍵。
                  
                      圖片來自:http://www.cnblogs.com/chjw8016/archive/2011/03/08/1976891.html

          Innodb表的限制

                  一個表不能包含超過1000列。

            內部最大鍵長度是3500字節,但MySQL自己限制這個到1024字節。

            除了VARCHAR, BLOBTEXT列,最大行長度稍微小于數據庫頁的一半。即,最大行長度大約8000字節。LONGBLOBLONGTEXT列必須小于4GB, 總的行長度,頁包括BLOBTEXT列,必須小于4GBInnoDB在行中存儲VARCHARBLOBTEXT列的前768字節,余下的存儲的分散的頁中。

          雖然InnoDB內部地支持行尺寸大于65535,你不能定義一個包含VARCHAR列的,合并尺寸大于65535的行。

          ·                mysql> CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),

          ·                    -> c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),

          ·                    -> f VARCHAR(10000), g VARCHAR(10000));

          ·                ERROR 1118 (42000): Row size too large. The maximum row size for the

          ·                used table type, not counting BLOBs, is 65535. You have to change some

          ·                columns to TEXT or BLOBs

           在一些更老的操作系統上,數據文件必須小于2GB

           InnoDB日志文件的合并尺寸必須小于4GB

          最小的表空間尺寸是10MB。最大的表空間尺寸是4,000,000,000個數據庫頁(64TB)。這也是一個表的最大尺寸。

           InnoDB表不支持FULLTEXT索引

           

          Innodb索引

          默認情況下Memory使用存儲hash索引,但也支持b+tree索引。Hash索引只用于=或者<=>的等式比較,不能用來加速order by操作,只能通過關鍵字來搜索一行。innodb只支持b+樹索引,進一步分為clustered index 與 secondary index。在一次查詢中,只能使用一個索引。

                  

          Innodb是索引組織表,clustered index的葉結點保存著整行的數據。如果,定義了primary key,則clustered index就是primary key的索引;如果沒有定義primary key mysql會選中第一個僅有not null列的unique索引作為主鍵,并把此索引當作clustered index使用;如果沒找到這樣的列,innodb會創建一個6字節的RowId作為主鍵。所以每張表有且只有一個clustered index

           

                   Secondary index的葉結點不包括行的全部數據,包含鍵值以外還包括一個bookmark,可以告訴innodb到什么地方可以找到相對應的完整行數據,還保存了主鍵的健值。Secondary index包含主鍵,但不包含完整的行數據,所以innodb總是會先從secondary index的葉節點判斷是否能得到所需的數據。如,

                   Create table t(a int, b varchar(20), primary key(a), key(b));

          Explain select * from t;

                   會發現mysql選擇了索引b,而不是a.

          復合索引

                   復合索引是在多列(>=2)上建立的索引,又叫多列索引或聯合索引。Innodb中的復合索引也是b+ tree結構。索引的數據包含多列(col1, col2, col3…),在索引中依次按照col1, col2, col3排序。如(1, 2), (1, 3),(2,0)…

           

                   使用復合索引要充分利用最左前綴原則,顧名思義,就是最左優先。如創建索引ind_col1_col2(col1, col2),那么在查詢where col1 = xxx and col2 = xx或者where col1 = xxx都可以走ind_col1_col2索引。

          在創建多列索引時,要根據業務需求,where子句中使用最頻繁且過濾效果好的的一列放在最左邊。

          索引操作

                   可以通過DML語句操作innodb索引。因為innodb是索引組織的表,對索引的操作會造成鎖表,先生成一張臨時表,將數據從原始表中寫到臨時表,再將原始表刪除,最后將臨時表表名改為原始表表名!因增加、刪除、修改字段會對主索引產生影響,所以也會鎖表。對secondary indexInnodb plugin開始,支持快速索引創建的方法,在創建的過程中不需要重建表,所以速度會很快,同時引擎會在表上加S鎖,在創建過程中只能進行讀操作。

          索引設計原則

          1.       搜索的索引列,不一定是所要選擇的列。也就是說,最適合索引的列是出現在where子句中的列,或者連接子句中指定的列,而不是出現在select關鍵字后的選擇列表中的列。

          2.       使用唯一索引。考慮某列的分布,索引的列的基數越大,索引的效果越好。例如,對性別M/F列做索引沒多大用處。

          3.       使用短索引。如果是對字符串進行索引,如果有可能應該指定前綴長度。

          4.       利用最左前綴。盡量將使用頻繁且過濾效果好的字段放“左邊”

          5.       不要過度索引。

          6.       Innodb默認會按照一定的順序保存數據,如果明確定義了主鍵,則按照主鍵順序保存。如果沒有主鍵,但有唯一索引,就按照唯一索引的順序保存。如果有幾個列都是唯一的,都可以作為主鍵的時候,為了提高查詢效率,應選擇最常用訪問的列作為主鍵。另外,innodbsecondary index都會保存主鍵的鍵值,所有主鍵要盡可能選擇較短的數據類型。可以看出,應當盡量避免對主鍵的修改。經過dba的測試,保證主鍵的遞增可以提高插入性能。

           

          Mysql如何使用索引

          1.       對于創建的多列索引,只要查詢的條件中用到了最左邊的列,索引一般就會被使用。

          2.       對于使用like的查詢,后面如果是常量并且只有%號不在第一個字符,索引才可能被使用。

          3.       如果對大文本進行搜索,應該使用全文索引,而不是使用like ‘%...%’. 但不幸的是innodb不支持全文索引。

          4.       如果列名是索引,使用 index_column is null將使用索引。Oracle是不行的。

          5.       如果mysql估計使用索引比全表掃描更慢,最不會使用索引。

          6.       如果使用memory/head表并且where條件中不使用”=”進行索引列,那么不會用到索引。Head表只有在”=”的時候才會使用索引。

          7.       or分割開的條件,如果or前的條件中的列有索引,而后面列中沒有索引,那么涉及到的索引都不會被用到。

          8.       不是多列索引的第一部分不會走索引。

          9.       %開始的like不會走索引

          10.   如果列是字符串,那么一定要在where條件中把字符串常量值用引號引起來,否則不能走索引。因為,mysql默認把輸入的常量值進行轉換以后才進行檢索。

          11.   經過普通運算或函數運算后的索引字段不能使用索引

          12.   不等于操作不能使用索,<>not in

          13.   Order by 優化:某些情況下,mysql可以使用一個索引滿足order by,而不需要額外的排序。Where條件與order by 使用相同的索引,并且order by的順序和索引順序相同,并且order by的字段都是升序或者都是降序。

          SELECT * FROM t1 ORDER BY key_part1,key_part2,... ;

          SELECT * FROM t1 WHERE key_part1=1 ORDER BY key_part1 DESC, key_part2

          DESC;

          SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 DESC;

          但是以下情況不使用索引:

          SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC

          --order by 的字段混合 ASC DESC

          SELECT * FROM t1 WHERE key2=constant ORDER BY key1

          -- 用于查詢行的關鍵字與 ORDER BY 中所使用的不相同

          SELECT * FROM t1 ORDER BY key1, key2

          -- 對不同的關鍵字使用 ORDER BY     

           

          可以使用explain查看sql的執行計劃。

          posted on 2011-12-17 16:36 happyenjoylife 閱讀(10256) 評論(2)  編輯  收藏

          評論

          # re: mysql innodb存儲與索引的總結 2013-11-19 22:24 T.H

          有個困惑想請教下站主,如果是多列組成的聯合索引這個B+Tree是什么結構?是所有列的數據的集合在一顆B+Tree大排列,還是每個列單獨一個B+Tree?  回復  更多評論   

          # re: mysql innodb存儲與索引的總結 2015-02-25 10:22 uranus

          @T.H
          是所有列的數據的集合在一顆B+Tree大排列  回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          <2013年11月>
          272829303112
          3456789
          10111213141516
          17181920212223
          24252627282930
          1234567

          統計

          常用鏈接

          留言簿

          隨筆檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 望奎县| 吉林市| 新田县| 武平县| 凤山市| 二连浩特市| 瓦房店市| 金溪县| 桦川县| 扎赉特旗| 和平区| 墨玉县| 永福县| 淮南市| 新和县| 临高县| 武穴市| 抚顺县| 砚山县| 象山县| 张家川| 余姚市| 英超| 兴化市| 新野县| 中卫市| 翼城县| 修水县| 普格县| 镇沅| 化隆| 庆阳市| 泾源县| 定兴县| 正镶白旗| 长治市| 天气| 昆明市| 仙桃市| 扎赉特旗| 鄂托克旗|