MySQL引擎、索引和優化(li)

1、存儲引擎mysql

  存儲引擎,MySQL中的數據用各類不一樣的技術存儲在文件(或者內存)中。這些技術中的每一種技術都使用不一樣的存儲機制、索引技巧、鎖定水平而且最終提供普遍的不一樣的功能和能力。經過選擇不一樣的技術,你可以得到額外的速度或者功能,從而改善你的應用的總體功能。InnoDB存儲引擎是5.5版本後Mysql的默認數據庫,事務型數據庫的首選引擎,支持ACID事務,支持行級鎖定。另外還有常見的MyISAM存儲引擎,它擁有較高的插入,查詢速度,但不支持事務。因此,很明顯:插入不頻繁,查詢很是頻繁,沒有事務,用MyISAM;可靠性要求高,表更新頻繁,事務多,用InnoDB算法

//#查看本機MySQL提供的什麼存儲引擎
//show ENGINES;
//
//#查看Mysql當前默認的存儲引擎
//show variables like '%storage_engine%';
//
//#查看當前表用什麼存儲引擎(DDL最後)
//show create table idc_work_order_main;

//#修改當前表的存儲引擎
//ALTER TABLE idc_work_order_main ENGINE = 'MyISAM'

  MySQL官方對InnoDB是這樣解釋的,InnoDB給MySQL提供了具備提交、回滾和奔潰恢復能力的事務安全存儲引擎。InnoDB是爲處理巨大數據量時的最大性能設計,它的CPU效率多是任何其它基於磁盤的關係數據庫引擎所不能匹敵的。InnoDB存儲引擎被徹底與MySQL服務器整合,InnoDB存儲引擎爲在主內存中緩存數據和索引而維持它本身的緩衝池。sql

  若是使用innodb存儲引擎,咱們知道該引擎最主要的特色是transactional和row lock(行級鎖)。按理說不會出現表鎖纔對,可是事實上仍是會出現鎖表的的狀況,也會比較嚴重,下面主要就是來探討一下這個問題。查看mysql文檔會發現,雖然innodb使用的的row lock(行級鎖),可是在處理具備auto increment字段的表的時候,會使用一種特殊的表鎖:AUTO-INC。簡單來講就是Innodb會在內存裏保存一個計數器用來記錄 auto_increment的值,當插入數據時,就會用一個表鎖來鎖住這個計數器,直到插入結束。一條一條插入問題不大,可是若是高併發插入,就會形成 sql阻塞。數據庫

  解決方案:1.不使用auto increment字段,本身維護主鍵生成。該方法中選擇主鍵生成策略很重要, 要綜合考慮簡單和效率問題。假設使用uuid,雖然簡單可是會形成該表的主鍵效率很低(innodb的主鍵是特殊的index,其餘的index會引用主鍵)。2.升級到最新的5.2版本。緩存

//#MySQL5.1.22版本以前,這種方式的特色就是「表級鎖定」,併發性較差
//innodb_autoinc_lock_mode = 0 (「traditional」 lock mode:所有使用表鎖)
//
//#推薦使用「consecutive」,併發性相對較高,特色是,即保證同一條insert語句中新插入的auto_increment id都是連續的
//innodb_autoinc_lock_mode = 1 (「consecutive」 lock mode)
//
//#這種模式是來一個分配一個,而不會鎖表,只會鎖住分配id的*過程*,和innodb_autoinc_lock_mode = 1的區別在於
//#不會預分配多個,這種方式併發性最高。可是在replication中當binlog_format爲statement-based時
//#(簡稱SBR statement-based replication)存在問題,由於是來一個分配一個,這樣當併發執行時,
//#「Bulk inserts」在分配時會同時向其餘的INSERT分配,會出現主從不一致(從庫執行結果和主庫執行結果不同),由於binlog只會記錄開始的 insert id。
//innodb_autoinc_lock_mode = 2 (「interleaved」 lock mode:所有使用新方式,不安全,不適合replication)

  關於數據的拷貝問題,經常使用的數據表引擎是MyISAM和InnoDB。MyISAM的數據表的後綴名是.frm(表結構)、.myd(數據)和.myi(索引),其索引和數據是分開的,能夠直接拷貝;InnoDB的數據表的後綴名是.frm(表結構)和.ibd(數據),索引和數據都在同個文件ibdata*,不能直接拷貝,須要先導出再導入。拷貝完以後別忘了重啓數據庫服務。安全

    

  既然是存儲引擎,那麼咱們看看這些數據庫的存儲是什麼樣的。block是相對於磁盤來說的,page是相對於內存來說的。第一幅圖是新建一個txt文檔,文件寫入1,而後再屬性中看佔用空間的大小,也就是一個block的大小是4k個字節。經過右圖的方式能夠用來查看內存中頁的大小。服務器

              

磁盤是分block塊的,同一表的數據頁是以鏈表的形式串聯在一塊兒的,數據庫數據按行存在各個block中,而且以block爲單位來存取數據。執行一條SQL的時候,從命令解析、肯定執行計劃、增刪改查。這樣磁盤的I/O帶來了性能問題。如何減小磁盤的I/O次數呢?數據結構

// 1.保證讀取數據量在合理大小
// 2.保證存取數據可以順序讀取
// 3.減小須要掃描數據佔用空間

保證讀取數據量在合理大小;保證存取數據可以順序讀取;減小須要掃描數據佔用空間。解決措施,就是使用index索引。dense index是稠密索引,也叫全索引。sparse index是稀疏索引。dense indexes是經過對每個record在磁盤上持久保存一些額外的數據,用於提升查詢的效率。Sparse index結合sequential file和dense index file的優勢,經過保存部分key K做爲它的record,能很好的支持二分查找快速查找record,而且能進一步減小所需的磁盤I/O。併發

                       

2、索引  高併發

  索引是幫助MySQL高效獲取數據的數據結構。介紹MySQL的索引結構,索引原理,進而學習索引的優化。MySQL的索引結構包括:B-tree索引、Tree索引、哈希索引(Hash)、位圖索引(Bitmap)、跳錶。

//#查看錶的當前索引  執行結果顯示(Index_type: BTREE)
//SHOW INDEX FROM idc_work_order_main

  命令用於查看咱們的數據庫中表的當前索引,執行結果顯示當前表結構使用功能的索引是BTREE。一般咱們經過以下方式給表建索引:

//#查詢表當前使用的索引(表的主鍵自動創建惟一索引unique index)
//SHOW INDEX FROM idc_work_order_main;
//
//#建立索引index
//CREATE INDEX aaa ON idc_work_order_main(remark)
//DROP INDEX aaa ON idc_work_order_main
//
//#建立惟一索引unique INDEX(惟一的索引意味着兩個行不能擁有相同的索引值,不然建立失敗)
//CREATE UNIQUE INDEX aaa ON idc_work_order_main(id)
//DROP INDEX aaa ON idc_work_order_main
//
//#建立組合索引
//CREATE INDEX aaa ON idc_work_order_main(id,remark)
//DROP INDEX aaa ON idc_work_order_main

咱們知道索引並非隨便亂建的,在考慮是否建索引時,咱們通常考慮以下的一些狀況:

  1.表記錄太少。若是一個表只有5條記錄,採用索引去訪問記錄的話,那首先需訪問索引表,再經過索引表訪問數據表,通常索引表與數據表不在同一個數據塊,這種狀況下至少要往返讀取數據塊兩次。而不用索引的狀況下ORACLE會將全部的數據一次讀出,處理速度顯然會比用索引快。

  2.常常插入、刪除、修改的表。對一些常常處理的業務表應在查詢容許的狀況下儘可能減小索引。

  3.數據重複,且分佈平均的表字段。假如一個表有10萬行記錄,有一個字段A只有T和F兩種值,且每一個值的分佈機率大約爲50%,那麼對這種表A字段建索引通常不會提升數據庫的查詢速度。

  創建索引,通常是在對針對百萬級以上的數據才創建索引的,以期來提升性能。在建立索引時,首先要考慮表空間和磁盤空間是否足夠。咱們知道索引也是一種數據,在創建索引的時候勢必也會佔用大量表空間。所以在對一大表創建索引的時候首先應當考慮的是空間容量問題。其次,在對創建索引的時候要對錶進行加鎖,所以應當注意操做在業務空閒的時候進行。其次考慮因素即是磁盤I/O。物理上應當儘可能把索引與數據分散到不一樣的磁盤上。邏輯上,數據表空間與索引表空間分開。這是在建索引時應當遵照的基本準則。

//通常狀況下不鼓勵使用like操做,若是非使用不可,如何使用也是一個問題。like 「%aaa%」 不會使用索引而like 「aaa%」可使用索引。
//NOT IN和操做都不會使用索引將進行全表掃描。NOT IN能夠NOT EXISTS代替,id3則可以使用id>3 or id

  索引結構,當前Mysql版本只有BTree和Hash兩種索引類型,默認爲BTree。Oracle或其餘類型數據庫中會有Bitmap索引(位圖索引)。下面將主要介紹B樹索引、哈希索引、位圖索引這三種索引結構。

  B樹(Blance Tree)索引,數據結構原型是多路搜索樹,它是一種常見的數據結構,經常使用作數據庫的索引。使用BTree結構能夠顯著減小定位記錄時所經歷的中間過程,從而加快存取速度。

// Blance Tree索引不適合的場景:
// 1.單列索引的列不能包含null的記錄,複合索引的各個列不能包含同時爲null的記錄,不然會全表掃描;
// 2.不適合鍵值較少的列(重複數據較多的列,is_deleted "y" "n");
// 3.前導模糊查詢不能利用索引(like '%XX'或者like '%XX%')

  圖片展現了B樹索引,在插入和刪除的時候,對Blance Tree的影響。

  哈希索引(Hash),Hash散列索引是根據HASH算法來構建的索引。雖然 Hash 索引效率高,可是 Hash 索引自己因爲其特殊性也帶來了不少限制和弊端,主要有如下這些:精確查找很是快(包括= <> 和in),其檢索效率很是高,索引的檢索能夠一次定位,不像BTree 索引須要從根節點到枝節點,因此 Hash 索引的查詢效率要遠高於 B-Tree 索引。

// Hash 索引不適合的場景:
// 1.不適合模糊查詢和範圍查詢(包括like,>,<,between……and等),因爲 Hash索引比較的是進行 Hash運算以後的 Hash值,因此它只能用於等值的過濾,不能用於基於範圍的過濾
//   由於通過相應的 Hash 算法處理以後的 Hash值的大小關係,並不能保證和Hash運算前徹底同樣;
// 2.不適合排序,數據庫沒法利用索引的數據來提高排序性能,一樣是由於Hash值的大小不肯定;
// 3.複合索引不能利用部分索引字段查詢,Hash索引在計算 Hash值的時候是組合索引鍵合併後再一塊兒計算Hash值,而不是單獨計算Hash值,
//   因此經過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也沒法被利用。
// 4.一樣不適合鍵值較少的列(重複值較多的列)

  位圖索引(Bitmap),就是用位圖表示的索引,對列的每一個鍵值創建一個位圖。相對於BTree索引,佔用的空間很是小,建立和使用很是快。位圖索引因爲只存儲鍵值的起止Rowid和位圖,佔用的空間很是少。

如test表中有state這樣一列,10行數據以下:

10    20    30    20    10    30    10    30    20    30

那麼會創建三個位圖,以下:

BLOCK1    KEY=10  1    0    0    0    1    0    1    0    0    0   
BLOCK2    KEY=20  1    0    0    0    1    0    1    0    0    0 
BLOCK3    KEY=30  1    0    0    0    1    0    1    0    0    0

//位圖索引適合場景:
//1.適合決策支持系統;
//2.當select count(XX) 時,能夠直接訪問索引中一個位圖就快速得出統計數據;
//3.當根據鍵值作and,or或 in(x,y,..)查詢時,直接用索引的位圖進行或運算,快速得出結果行數據。

//位圖索引不適合場景:
//1.不適合鍵值較多的列(重複值較少的列);
//2.不適合update、insert、delete頻繁的列,代價很高。

  跳錶,利用了鏈表的結構圖。一個節點存儲了下下一個節點的信息,讓性能提高了一倍。

 

3、MySQL優化

  1.limit start, count分頁的優化,limit語句的查詢時間與起始位置(start)的位置成正比。建議加索引,利用MySQL提供的索引緩存,不要直接去找數據地址,而是去索引地址先去查索引。

  2.表的數據類型,能小就小,能用char(1)就不用varchar。避免使用null,count(列)不統計值爲null的行數,且不利於索引。

  3.char是固定大小,varchar能夠動態存儲數據。優先用tinyint、smallint,再用int、bigint。

  4.在存儲相同數值範圍的數據時,浮點數類型float一般都會比decimal類型使用更少的空間。float字段使用4字節存儲數據。double類型須要8個字節並擁有更高的精確度和更大的數值範圍,decimal類型的數據將會轉換成double類型。

 

 

附錄:

一、全文索引,全文索引技術是目前搜索引擎的關鍵技術。試想在1M大小的文件中搜索一個詞,可能須要幾秒,在100M的文件中可能須要幾十秒,若是在更大的文件中搜索那麼就須要更大的系統開銷,這樣的開銷是不現實的因此在這樣的矛盾下出現了全文索引技術。InnoDB不支持,Myisam支持性能比較好,通常在 CHAR、VARCHAR 或 TEXT 列上建立。

2.彙集索引,該索引中鍵值的邏輯順序決定了表中相應行的物理順序。 彙集索引肯定表中數據的物理順序。Mysql中myisam表是沒有彙集索引的,innodb有(主鍵就是彙集索引),彙集索引在下面介紹innodb結構的時有詳細介紹。

相關文章
相關標籤/搜索