Mysql知識點整理

索引相關

索引類型

主鍵索引:數據列不容許重複,不容許爲NULL。一個表只能有一個主鍵索引。InnoDB的主鍵索引爲聚簇索引,而MyISAM的主鍵索引爲非聚簇索引。 建立:ALTER TABLE table_name ADD PRIMARY KEY (column);mysql

惟一索引:數據列不容許重複,容許爲NULL,一個表中容許建立多個惟一索引。惟一索引能夠用做業務防重。 建立:ALTER TABLE table_name ADD UNIQUE (column1, column2);git

普通索引:基本的索引類型,沒有惟一性的限制,容許爲NULL值。 建立:ALTER TABLE table_name ADD KEY (column1, column2)github

全文索引:是目前搜索引擎使用的一種關鍵技術,InnoDB不支持全文索引,MyISAM支持全文索引。 建立:ALTER TABLE table_name ADD FULLTEXT (column);算法

最左前綴原則

聯合索引從左邊的列到右邊的列依次匹配,聯合索引的最左前綴原則以下: 對於聯合索引:index(co1, col2, col3)sql

  1. where col1=1where col1=1 and col2=2where col1=1 and col2=2 and col3=3都會走這個索引。第一個語句使用 col1,第二個語句使用 col1,col2,第三個使用 col1,col2,col3;
  2. where col2=2where col2=2 and col3=3不會走索引;
  3. where col3=3 and col2=2 and col1=1未經查詢優化的話不會走索引,可是通過查詢優化後會走索引...;
  4. where col1=1 and col3=3 僅使用 col1;
  5. where col1=1 and col2>2 and col3=3 僅使用 col1,col2;
  6. where col1=1 and col2 like 'xx%' 使用 col1,col2;
  7. where col1=1 and col2 like '%xx'' 僅使用 col1。

索引算法(B-Tree 和 HASH)

B-Tree索引數據庫

B-Tree索引是一棵多路查找平衡樹,InnoDB 和 MyISAM 存儲引擎都支持 B-Tree 索引。InnoDB 支持聚簇索引,InnoDB 默認會爲主鍵建立聚簇索引,聚簇索引的非葉子節點不保存數據,只有葉子節點會保存數據,聚簇索引的葉子節點還會保存相鄰的後一個節點的指針。非聚簇索引葉子節點不保存數據,只保存主鍵索引。緩存

HASH索引安全

Hash 索引檢索效率高,只須要一次定位,不像 B-Tree 索引須要從根節點到葉子節點,最後才能訪問到頁節點這樣屢次的IO訪問。 Hash索引雖然檢索效率高,可是也有不少的不足之處:併發

  1. Hash 索引僅僅能知足」=」,」IN」和」<=>」查詢,不能使用範圍查詢。 因爲 Hash 索引比較的是進行 Hash 運算以後的 Hash 值,因此它只能用於等值的過濾,不能用於基於範圍的過濾,由於通過相應的 Hash 算法處理以後的 Hash 值的大小關係,並不能保證和Hash運算前徹底同樣。函數

  2. Hash 索引沒法被用來避免數據的排序操做。 因爲 Hash 索引中存放的是通過 Hash 計算以後的 Hash 值,並且 Hash 值的大小關係並不必定和 Hash 運算前的鍵值徹底同樣,因此數據庫沒法利用索引的數據來避免任何排序運算;

  3. Hash 索引不能利用部分索引鍵查詢。 對於組合索引,Hash 索引在計算 Hash 值的時候是組合索引鍵合併後再一塊兒計算 Hash 值,而不是單獨計算 Hash 值,因此經過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也沒法被利用。

  4. Hash 索引在任什麼時候候都不能避免表掃描。 前面已經知道,Hash 索引是將索引鍵經過 Hash 運算以後,將 Hash運算結果的 Hash 值和所對應的行指針信息存放於一個 Hash 表中,因爲不一樣索引鍵存在相同 Hash 值,因此即便取知足某個 Hash 鍵值的數據的記錄條數,也沒法從 Hash 索引中直接完成查詢,仍是要經過訪問表中的實際數據進行相應的比較,並獲得相應的結果。

  5. Hash 索引遇到大量Hash值相等的狀況後性能並不必定就會比B-Tree索引高。 對於選擇性比較低的索引鍵,若是建立 Hash 索引,那麼將會存在大量記錄指針信息存於同一個 Hash 值相關聯。這樣要定位某一條記錄時就會很是麻煩,會浪費屢次表數據的訪問,而形成總體性能低下。

B-Tree vs. HASH索引

索引名 HASH B-Tree
是否支持最左前綴匹配原則 不支持,只有索引的所有字段都用上纔會匹配到 支持,用上索引的第一個字段就能夠匹配索引
MyISAM和InnoDB是否支持 不支持(只有Memory和NDB引擎索引支持) 支持
範圍查詢可否命中索引 不能夠,只有「=」,「IN」,「<=>」(等價於的意思)查詢能命中 能夠
是否必定會全表掃描

索引設計原則

  1. 爲常常須要排序、分組和聯合的字段創建索引
  2. 爲常常做爲 where 條件查詢的字段創建索引
  3. 在選擇性好的列上創建索引,所謂選擇性好是指篩選出來的數據少,例如性別的選擇性就比較差,而姓名的選擇性就高
  4. 聯合索引須要注意索引的順序,將選擇性高的放在前面
  5. 索引雖然能加快查詢,可是索引也是有代價的,首先索引會佔用存儲空間。其次索引的維護也是有消耗的。所以,索引不是越多越好。

數據類型

數字類型

整數: tinyint、smallint、mediumint、int、bigint

type Storage Minumun Value Maximum Value
(Bytes) (Signed/Unsigned) (Signed/Unsigned)
TINYINT 1 -128 127
0 255
SMALLINT 2 -32768 32767
0 65535
MEDIUMINT 3 -8388608 8388607
0 16777215
INT 4 -2147483648 2147483647
0 4294967295
BIGINT 8 -9223372036854775808 9223372036854775807
0 18446744073709551615

浮點數: float、double、real、decimal

屬性 存儲空間 精度 精確性 說明
FLOAT(M, D) 4 bytes 單精度 非精確 單精度浮點型,m總個數,d小數位
DOUBLE(M, D) 8 bytes 雙精度 比Float精度高 雙精度浮點型,m總個數,d小數位

FLOAT容易形成精度丟失

定點數DECIMAL

  1. 高精度的數據類型,經常使用來存儲交易相關的數據
  2. DECIMAL(M,N).M表明總精度,N表明小數點右側的位數(標度)1 < M < 254, 0 < N < 60;
  3. 存儲空間變長

日期和時間

date、time、datetime、timestamp、year

類型 字節 精確性
DATE 三字節 2015-05-01 精確到年月日
TIME 三字節 11:12:00 精確到時分秒
DATETIME 八字節 2015-05-01 11::12:00 精確到年月日時分秒
TIMESTAMP 2015-05-01 11::12:00 精確到年月日時分秒
  • MySQL在5.6.4版本以後,TIMESTAMPDATETIME支持到微秒。
  • TIMESTAMP會根據系統時區進行轉換,DATETIME則不會
  • 存儲範圍的區別
    • TIMESTAMP存儲範圍:1970-01-01 00::00:01 to 2038-01-19 03:14:07
    • DATETIME的存儲範圍:1000-01-01 00:00:00 to 9999-12-31 23:59:59
  • 通常使用TIMESTAMP國際化
  • 如存時間戳使用數字類型BIGINT

字符串類型

字符串: char、varchar 文本: tinytext、text、mediumtext、longtext

類型 單位 最大 特性
CHAR 字符 最大爲255字符 存儲定長,容易形成空間的浪費
VARCHAR 字符 能夠超過255個字符 存儲變長,節省存儲空間
TEXT 字節 總大小爲65535字節,約爲64KB -
  • TEXT在MySQL內部大多存儲格式爲溢出頁,效率不如CHAR
  • Mysql默認爲utf-8,那麼在英文模式下1個字符=1個字節,在中文模式下1個字符=3個字節。

二進制(可用來存儲圖片、音樂等)

tinyblob、blob、mediumblob、longblob

InnoDB和MyISAM的區別

  • InnoDB支持事務,MyISAM不支持。
  • MyISAM適合查詢以及插入爲主的應用,InnoDB適合頻繁修改以及涉及到安全性較高的應用。
  • InnoDB支持外鍵,MyISAM不支持。
  • 從MySQL5.5.5之後,InnoDB是默認引擎。
  • InnoDB不支持FULLTEXT類型的索引。
  • InnoDB中不保存表的行數,如select count() from table時,InnoDB須要掃描一遍整個表來計算有多少行,可是MyISAM只要簡單的讀出保存好的行數便可。主要的是,當count()語句包含where條件時MyISAM也須要掃描整個表。
  • 對於自增加的字段,InnoDB中必須包含只有該字段的索引,可是在MyISAM表中能夠和其餘字段一塊兒創建聯合索引。
  • 清空整個表時,InnoDB是一行一行的刪除,效率很是慢。MyISAM則會重建表。
  • InnoDB支持行鎖(某些狀況下仍是會鎖整個表,如update table set a = 1 where user like '%lee%')

MVCC

MVCC的實現,是經過保存數據在某個時間點的快照來實現的,根據事務開始時間的不一樣,每一個事務對於同一張表,同一時刻看到的數據多是不一樣的。

InnoDB的 MVCC ,是經過在每行記錄的後面保存兩個隱藏的列來實現的。這兩個列,一個保存了行的建立時間,一個保存了行的過時時間(或刪除時間), 固然存儲的並非實際的時間值,而是系統版本號。

能夠認爲MVCC是行級鎖的一個變種,可是它在不少狀況下避免了加鎖操做,所以開銷更低。雖然實現機制有所不一樣,但大都實現了非阻塞的讀操做,寫操做也只鎖定必要的行。

在MVCC協議下,每一個讀操做會看到一個一致性的 snapshot,而且能夠實現非阻塞的讀。MVCC 容許數據具備多個版本,這個版本能夠是時間戳或者是全局遞增的事務 ID,在同一個時間點,不一樣的事務看到的數據是不一樣的。

  • select:知足如下兩個條件innodb會返回該行數據:(1)該行的建立版本號小於等於當前版本號,用於保證在select操做以前全部的操做已經執行落地。(2)該行的刪除版本號大於當前版本或者爲空。刪除版本號大於當前版本意味着有一個併發事務將該行刪除了。
  • insert:將新插入的行的建立版本號設置爲當前系統的版本號。
  • delete:將要刪除的行的刪除版本號設置爲當前系統的版本號。
  • update:不執行原地update,而是轉換成insert + delete。將舊行的刪除版本號設置爲當前版本號,並將新行insert同時設置建立版本號爲當前版本號。

其中,寫操做(insert、delete和update)執行時,須要將系統版本號遞增。 因爲舊數據並不真正的刪除,因此必須對這些數據進行清理,innodb會開啓一個後臺線程執行清理工做,具體的規則是將刪除版本號小於當前系統版本的行刪除,這個過程叫作purge。 經過MVCC很好的實現了事務的隔離性,能夠達到repeated read級別,要實現serializable還必須加鎖。

MVCC只在READ COMMITED 和 REPEATABLE READ 兩個隔離級別下工做。READ UNCOMMITTED老是讀取最新的數據行,而不是符合當前事務版本的數據行。而SERIALIZABLE 則會對全部讀取的行都加鎖。

InnoDB間隙鎖

Record lock

單條索引記錄上加鎖,InnoDB 的行鎖是經過索引實現的,如沒有索引,則鎖住的不是記錄行而是整個表。

Gap lock

間隙鎖,鎖定一個範圍,但不包括記錄自己。GAP鎖的目的,是爲了防止同一事務的兩次當前讀,出現幻讀的狀況。

Next-key lock

Next-key lock 就是 Record lock + Gap lock 的組合,它鎖定的是一個範圍,而且鎖定記錄自己。對於行的查詢,都是採用該方法,主要目的是解決幻讀的問題。

間隙鎖(Next-key lock)的條件

mysql的事務隔離級別是可重複讀(RR,Repeatable Read),而且 innodb_locks_unsafe_for_binlog 參數設置爲0

事務ACID

  1. 原子性(Atomicity):不可分割的操做單元,事務中全部操做,要麼所有成功;要麼撤回到執行事務以前的狀態
  2. 一致性(Consistency):若是在執行事務以前數據庫是一致的,那麼在執行事務以後數據庫也仍是一致的;
  3. 隔離性(Isolation):事務操做之間彼此獨立和透明互不影響。事務獨立運行。這一般使用鎖來實現。一個事務處理後的結果,影響了其餘事務,那麼其餘事務會撤回。事務的100%隔離,須要犧牲速度。
  4. 持久性(Durability):事務一旦提交,其結果就是永久的。即使發生系統故障,也能恢復。

delete drop truncate區別

truncate 和 delete只刪除數據,不刪除表結構 ,drop刪除表結構,而且釋放所佔的空間。

刪除數據的速度,通常來講: drop> truncate > delete

delete屬於DML語言,須要事務管理,commit以後才能生效。drop和truncate屬於DDL語言,操做馬上生效,不可回滾

使用場合:

  • 當你再也不須要該表時,用 drop;
  • 當你仍要保留該表,但要刪除全部記錄時, 用 truncate;
  • 當你要刪除部分記錄時(always with a where clause), 用 delete.

Mysql explain

explain 用於查看 SQL 語句執行計劃,其結果主要包含如下幾個重要參數:id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra,下面對這些字段出現的可能進行解釋。

select_type

表示查詢中每一個select子句的類型

  • SIMPLE(簡單SELECT,不使用UNION或子查詢等)
  • PRIMARY(查詢中若包含任何複雜的子部分,最外層的select被標記爲PRIMARY)
  • UNION(UNION中的第二個或後面的SELECT語句)
  • DEPENDENT UNION(UNION中的第二個或後面的SELECT語句,取決於外面的查詢)
  • UNION RESULT(UNION的結果)
  • SUBQUERY(子查詢中的第一個SELECT)
  • DEPENDENT SUBQUERY(子查詢中的第一個SELECT,取決於外面的查詢)
  • DERIVED(派生表的SELECT, FROM子句的子查詢)
  • UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須從新評估外連接的第一行)

type

表示MySQL在表中找到所需行的方式,又稱「訪問類型」。

經常使用的類型有: ALL, index, range, ref, eq_ref, const, system, NULL(從左到右,性能從差到好)

  • ALL:Full Table Scan, MySQL將遍歷全表以找到匹配的行
  • index: Full Index Scan,index與ALL區別爲index類型只遍歷索引樹
  • range:只檢索給定範圍的行,使用一個索引來選擇行
  • ref: 表示上述表的鏈接匹配條件,即哪些列或常量被用於查找索引列上的值
  • eq_ref: 相似ref,區別就在使用的索引是惟一索引,對於每一個索引鍵值,表中只有一條記錄匹配,簡單來講,就是多表鏈接中使用primary key或者 unique key做爲關聯條件
  • const、system: 當MySQL對查詢某部分進行優化,並轉換爲一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量,system是const類型的特例,當查詢的表只有一行的狀況下,使用system
  • NULL: MySQL在優化過程當中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裏選取最小值能夠經過單獨索引查找完成。

possible_keys

指出MySQL能使用哪一個索引在表中找到記錄,查詢涉及到的字段上若存在索引,則該索引將被列出,但不必定被查詢使用 該列徹底獨立於EXPLAIN輸出所示的表的次序。這意味着在possible_keys中的某些鍵實際上不能按生成的表次序使用。 若是該列是NULL,則沒有相關的索引。在這種狀況下,能夠經過檢查WHERE子句看是否它引用某些列或適合索引的列來提升你的查詢性能。若是是這樣,創造一個適當的索引而且再次用EXPLAIN檢查查詢

Key

key列顯示MySQL實際決定使用的鍵(索引) 若是沒有選擇索引,鍵是NULL。要想強制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。

explain 總結

  • EXPLAIN不會告訴你關於觸發器、存儲過程的信息或用戶自定義函數對查詢的影響狀況
  • EXPLAIN不考慮各類Cache
  • EXPLAIN不能顯示MySQL在執行查詢時所做的優化工做
  • 部分統計信息是估算的,並不是精確值
  • EXPALIN只能解釋SELECT操做,其餘操做要重寫爲SELECT後查看執行計劃。

參考資料

ningyu1.github.io/site/post/5…
MySQL 的 MVCC 原理
MySQL - 索引詳解

相關文章
相關標籤/搜索