在mysql客戶端中,使用如下命令能夠查看MySQL支持的引擎。html
show engines;
下面咱們重點介紹幾種經常使用的存儲引擎並對比各個存儲引擎之間的區別和推薦使用方式。mysql
特色 | Myisam | BDB | Memory | InnoDB | Archive |
---|---|---|---|---|---|
存儲限制 | 沒有 | 沒有 | 有 | 64TB | 沒有 |
事務安全 | 支持 | 支持 | |||
鎖機制 | 表鎖 | 頁鎖 | 表鎖 | 行鎖 | 行鎖 |
B樹索引 | 支持 | 支持 | 支持 | 支持 | |
哈希索引 | 支持 | 支持 | |||
全文索引 | 支持 | ||||
集羣索引 | 支持 | ||||
數據緩存 | 支持 | 支持 | |||
索引緩存 | 支持 | 支持 | 支持 | ||
數據可壓縮 | 支持 | 支持 | |||
空間使用 | 低 | 低 | N/A | 高 | 很是低 |
內存使用 | 低 | 低 | 中等 | 高 | 低 |
批量插入的速度 | 高 | 高 | 高 | 低 | 很是高 |
支持外鍵 | 支持 |
最常使用的2種存儲引擎:算法
選擇標準能夠分爲:
(1)是否須要支持事務;
(2)是否須要使用熱備;
(3)崩潰恢復:可否接受崩潰;
(4)是否須要外鍵支持;sql
根據應用特色選擇合適的存儲引擎,對於複雜的應用系統能夠根據實際狀況選擇多種存儲引擎進行組合。
下面是經常使用存儲引擎的適用環境:數據庫
基本配置:編程
datadir:指定mysql的數據目錄位置,用於存放mysql數據庫文件、日誌文件等。緩存
配置示例:datadir=D:/wamp/mysqldata/Data安全
default-character-set:mysql服務器默認字符集設置。服務器
配置示例:default-character-set=utf8網絡
skip-grant-tables:當忘記mysql用戶密碼的時候,能夠在mysql配置文件中配置該參數,跳過權限表驗證,不須要密碼便可登陸mysql。
日誌相關:
log-error:指定錯誤日誌文件名稱,用於記錄當mysqld啓動和中止時,以及服務器在運行過程當中發生任何嚴重錯誤時的相關信息。
配置示例:log-error="WJT-PC.err"(默認在mysql數據目錄下)
log-bin:指定二進制日誌文件名稱,用於記錄對數據形成更改的全部查詢語句。
配置示例:log-bin="WJT-PC-bin.log"(默認在mysql數據目錄下)
binlog-do-db:指定將更新記錄到二進制日誌的數據庫,其餘全部沒有顯式指定的數據庫更新將被忽略,不記錄在日誌中。
配置示例:binlog-do-db=db_name
binlog-ignore-db:指定不將更新記錄到二進制日誌的數據庫,其餘沒有顯式忽略的數據庫都將進行記錄。
配置示例:binlog-ignore-db=db_name
若是想記錄或忽略多個數據庫,能夠對上面兩個選項分別使用屢次。
sync-binlog:指定多少次寫日誌後同步磁盤。
配置示例:sync-binlog=N
general-log:是否開啓查詢日誌記錄。
配置示例:general-log=1
general_log_file:指定查詢日誌文件名,用於記錄全部的查詢語句。
配置示例:general_log_file="WJT-PC.log"(默認在mysql數據目錄下)
slow-query-log:是否開啓慢查詢日誌記錄。
配置示例:slow-query-log=1
slow_query_log_file:指定慢查詢日誌文件名稱,用於記錄消耗時間較長的查詢語句。
配置示例:slow_query_log_file="WJT-PC-slow.log"(默認在mysql數據目錄下)
long_query_time:設置慢查詢的時間,超過這個時間的查詢語句才記錄日誌。
配置示例:long_query_time=10(單位:秒)
log-slow-admin-statements:是否將慢管理語句(例如OPTIMIZE TABLE、ANALYZE TABLE和ALTER TABLE)寫入慢查詢日誌。
存儲引擎相關:
default-table-type:設置mysql的默認存儲引擎。
innodb_data_home_dir:InnoDB引擎的共享表空間數據文件根目錄。若沒有設置,則使用mysql的datadir目錄做爲缺省目錄。
innodb_data_file_path:單獨指定共享表空間數據文件的路徑與大小。數據文件的完整路徑由innodb_data_home_dir與這裏配置的值組合起來,文件大小以MB單位指定。
配置示例:innodb_data_home_dir=
innodb_data_file_path=ibdata1:12M;/data/mysql/mysql3306/data1/ibdata2:12M:autoextend
若是想爲innodb表空間指定不一樣目錄下的文件,必須指定 innodb_data_home_dir =。這個例子中會在datadir下創建ibdata1,在/data/MySQL/mysql3306/data1/目錄下建立ibdata2。
innodb_file_per_table:是否開啓獨立表空間,若開啓,InnoDB將使用獨立的.idb文件建立新表而不是在共享表空間中建立。
配置示例:innodb_file_per_table=1
innodb_autoinc_lock_mode:配置在向有着auto_increment列的表插入數據時,相關鎖的行爲。該參數有3個取值,0:tradition傳統,全部的insert語 句開始的時候獲得一個表級的auto_inc鎖,在語句結束的時候才能釋放 這個鎖,影響了併發的插入。1:consecutive連續,mysql能夠一次生成 幾個連續的auto_inc的值,auto_inc不須要一直保持到語句結束,只要 語句獲得了相應的值後就能夠提早釋放鎖(這也是mysql的默認模式)。 2:interleaved交錯,這個模式下已經沒有了auto_inc鎖,因此性能是最好的,可是對於同一個語句來講它獲得的auto_inc的值可能不是連續的。
配置示例:innodb_autoinc_lock_mode=1
low_priority_updates:在myisam引擎鎖使用中,默認狀況下寫請求優先於讀請求,能夠經過將該參數設置爲1來使myisam引擎給予讀請求優先權限, 全部的insert、update、delete和lock table write語句將等待直到受影響 的表沒有掛起的select或lock table read。
配置示例:low_priority_updates=0(默認配置)
max_write_lock_count:當一個myisam表的寫鎖定達到這個值後,mysql就暫時 將寫請求優先級下降,給部分讀請求得到鎖的機會。
innodb_lock_wait_timeout:InnoDB鎖等待超時參數,若事務在該時間內沒有獲 得須要的鎖,則發生回滾。
配置示例:innodb_lock_wait_timeout=50(默認50秒)
max_heap_table_size:設置memory表的最大空間大小,該變量能夠用來計算 memory表的max_rows值。在已有memory表上設置該參數是沒有效果 的,除非重建表。
查詢相關:
max_sort_length:配置對blob或text類型的列進行排序時使用的字節數(只對配置的前max_sort_length個字節進行排序,其餘的被忽略)
max_length_for_sort:mysql有兩種排序算法,兩次傳輸排序和單次傳輸排序。當查詢須要全部列的總長度不超過max_length_for_sort時,mysql使用 單次傳輸排序,不然使用兩次傳輸排序。
optimizer_search_depth:在關聯查詢中,當須要關聯的表數量超過optimizer_search_depth的時候,優化器會使用「貪婪」搜索的方式查找「最優」的關聯順序。
熱備:國內大部分採用的是雙機熱備的方式
組成雙機熱備的方案主要的三種方式分別爲:基於共享存儲(磁盤陣列)的方式,全冗餘方式和複製方式。
基於共享存儲(磁盤陣列)的方式
共享存儲方式主要經過磁盤陣列提供切換後,對數據完整性和連續性的保障。用戶數據通常會放在磁盤陣列上,當主機宕機後,備機繼續從磁盤陣列上取得原有數據。以下圖所示傳統的單存儲方式這種方式由於使用一臺存儲設備,每每被業內人士稱爲磁盤單點故障。但通常來說存儲的安全性較高。因此若是忽略存儲設備故障的狀況下,這種方式也是業內採用最多的熱備方式。
全冗餘方式
全冗餘方式就是雙機雙存儲,基於單臺存儲的傳統雙機熱備方式,確實存在存儲單點故障的狀況,爲實現存儲冗餘,存儲高可用也已經愈來愈多的被用戶接受。咱們從理解上能夠看出,雙機熱備最先是爲解決服務器的計劃性停機與非計劃性宕機的解決方案,可是咱們沒法實現存儲的計劃性停機與非計劃性宕機帶來的服務器停機,而存儲做爲雙機熱備中惟一存儲數據的設備,它一旦發生故障每每會形成雙機熱備系統全面崩潰。存儲熱備方式隨着科技的進步,雲存儲,雲計算發展,對於存儲熱備已經進入了成熟及快速發展階段,雙機熱備也隨着技術的進步,進入到了沒有單點故障的全冗餘雙機熱備方式。
這種方式的特色在於:
一、存儲之間的數據複製不通過網絡,而是由存儲之間進行復制。
二、兩個存儲之間的複製是徹底實時的,不存在任什麼時候間延時。
三、主備存儲之間的切換時間小於500ms,以確保系統存儲時不產生延時。
四、硬盤盤符及分區不由於主備存儲之間的切換而改變。
五、服務器的切換,不影響存儲之間的初始化,增量同步及數據複製。
六、某一存儲設備的計劃性停機,不影響整個服務器雙機熱備系統的工做。
七、存儲設備之間使用重複數據刪除技術,完成增量同步工做。
八、真正的7X24小時或切換的全冗餘方案。
複製方式
這種方式主要利用數據的同步方式,保證主備服務器的數據一致性。
基於數據複製的方式有多種方法,其性能和安全也不盡相同,其主要方法有如下幾種:
A、單純的文件方式的拷貝不適用於數據庫等應用,由於打開的文件是不能被複制的,若是要複製必須將數據庫關閉,這顯然是不能夠的。以文件方式的複製主要適用於WEB頁的更新,FTP上傳應用,對主備機數據完整性,連續性要數據同步方式求不高的狀況下使用。
B、利用數據庫所帶有複製功能,好比SQLServer2000或2005所帶的定閱複製,這種方式用戶要根據本身的應用當心使用,緣由主要是:
(1)SQLServer的定閱複製會在用戶表上增長字段,對那些應用軟件編程要求較高,若是在應用軟件端書寫時未明確指定字段的用戶,而使用此功能會形成應用程序沒法正常工做。
(2)數據滯留,這個限制怕也是最要命的,由於SQLServer在數據傳輸過程當中數據並不是實時的到達主備機,而是數據先寫到主機,再寫到備機,如此一來,備機的數據每每來不及更新,此時若是發生切換,備機的數據將不完整,也不連續,若是用戶發現已寫入的數據在備機找不到,從新寫入的話,則主機修復後,就會發生主備機數據嚴重衝突,數據庫會亂掉。
(3)複雜應用切莫使用定閱複製來作雙機熱備,包括數據結構中存儲過程的處理,觸發器和序列,一旦發生衝突,修改起來很是麻煩。
(4)服務器性能下降,對於大一點的數據庫,SQLServer2000或2005所帶的定閱複製會形成服務器數據庫運行緩慢。
總之SQLServer2000或2005所帶的定閱複製主要仍是應用於數據快照服務,切莫用他來作雙機熱備中的數據同步。
C:硬盤數據攔截,目前國際國內,比較成熟的雙機熱備軟件一般會使用硬盤數據攔截的技術,一般稱爲鏡像軟件即Mirror軟件,這種技術當前已很是成熟,攔截的方式也不盡相同。
(1)分區攔截技術,以Pluswell熱備份產品爲例,他採用的是一種分區硬盤扇區攔截的技術,經過驅動級的攔截方式,將數據寫往硬盤的數據提取,並首先寫到備用服務器,以保證備用服務器的數據最新,而後再將數據回寫到主機硬盤。這種方式將絕對保證,主備機數據庫的數據徹底一致,不管發生哪一種切換,都能保證數據庫的完整性與連續性。因爲採用分區攔截技術,因此用戶能夠根據須要在一塊硬盤上劃分適合大小的分區來完成數據同步工做。
(2)硬盤攔截技術,以Symantec的Co-Standby爲例,也是一種有效的硬盤攔截軟件,他的攔截主要基於一整塊硬盤,每每在硬盤初始化時須要消耗大量的時間。
1.減小 IO 次數
IO永遠是數據庫最容易瓶頸的地方,這是由數據庫的職責所決定的,大部分數據庫操做中超過90%的時間都是 IO 操做所佔用的,減小 IO 次數是 SQL 優化中須要第一優先考慮,固然,也是收效最明顯的優化手段。
2.下降 CPU 計算
除了 IO 瓶頸以外,SQL優化中須要考慮的就是 CPU 運算量的優化了。order by, group by,distinct … 都是消耗 CPU 的大戶(這些操做基本上都是 CPU 處理內存中的數據比較運算)。當咱們的 IO 優化作到必定階段以後,下降 CPU 計算也就成爲了咱們 SQL 優化的重要目標
改變 SQL 執行計劃
明確了優化目標以後,咱們須要肯定達到咱們目標的方法。對於 SQL 語句來講,達到上述2個目標的方法其實只有一個,那就是改變 SQL 的執行計劃,讓他儘可能「少走彎路」,儘可能經過各類「捷徑」來找到咱們須要的數據,以達到 「減小 IO 次數」 和 「下降 CPU 計算」 的目標
1.count(1)和count(primary_key) 優於 count(*)
不少人爲了統計記錄條數,就使用 count(1) 和 count(primary_key) 而不是 count(*) ,他們認爲這樣性能更好,其實這是一個誤區。對於有些場景,這樣作可能性能會更差,應爲數據庫對 count(*) 計數操做作了一些特別的優化。
2.count(column) 和 count(*) 是同樣的
這個誤區甚至在不少的資深工程師或者是 DBA 中都廣泛存在,不少人都會認爲這是理所固然的。實際上,count(column) 和 count(*) 是一個徹底不同的操做,所表明的意義也徹底不同。
count(column) 是表示結果集中有多少個column字段不爲空的記錄
count(*) 是表示整個結果集有多少條記錄
3.select a,b from … 比 select a,b,c from … 可讓數據庫訪問更少的數據量
這個誤區主要存在於大量的開發人員中,主要緣由是對數據庫的存儲原理不是太瞭解。
實際上,大多數關係型數據庫都是按照行(row)的方式存儲,而數據存取操做都是以一個固定大小的IO單元(被稱做 block 或者 page)爲單位,通常爲4KB,8KB… 大多數時候,每一個IO單元中存儲了多行,每行都是存儲了該行的全部字段(lob等特殊類型字段除外)。
因此,咱們是取一個字段仍是多個字段,實際上數據庫在表中須要訪問的數據量實際上是同樣的。
固然,也有例外狀況,那就是咱們的這個查詢在索引中就能夠完成,也就是說當只取 a,b兩個字段的時候,不須要回表,而c這個字段不在使用的索引中,須要回表取得其數據。在這樣的狀況下,兩者的IO量會有較大差別。
4.order by 必定須要排序操做
咱們知道索引數據其實是有序的,若是咱們的須要的數據和某個索引的順序一致,並且咱們的查詢又經過這個索引來執行,那麼數據庫通常會省略排序操做,而直接將數據返回,由於數據庫知道數據已經知足咱們的排序需求了。
實際上,利用索引來優化有排序需求的 SQL,是一個很是重要的優化手段
延伸閱讀:MySQL ORDER BY 的實現分析,MySQL 中 GROUP BY 基本實現原理以及 MySQL DISTINCT 的基本實現原理這3篇文章中有更爲深刻的分析,尤爲是第一篇
5.執行計劃中有 filesort 就會進行磁盤文件排序
有這個誤區其實並不能怪咱們,而是由於 MySQL 開發者在用詞方面的問題。filesort 是咱們在使用 explain 命令查看一條 SQL 的執行計劃的時候可能會看到在 「Extra」 一列顯示的信息。
實際上,只要一條 SQL 語句須要進行排序操做,都會顯示「Using filesort」,這並不表示就會有文件排序操做。
1.儘可能少 join
MySQL 的優點在於簡單,但這在某些方面其實也是其劣勢。MySQL 優化器效率高,可是因爲其統計信息的量有限,優化器工做過程出現誤差的可能性也就更多。對於複雜的多表 Join,一方面因爲其優化器受限,再者在 Join 這方面所下的功夫還不夠,因此性能表現離 Oracle 等關係型數據庫前輩仍是有必定距離。但若是是簡單的單表查詢,這一差距就會極小甚至在有些場景下要優於這些數據庫前輩。
2.儘可能少排序
排序操做會消耗較多的 CPU 資源,因此減小排序能夠在緩存命中率高等 IO 能力足夠的場景下會較大影響 SQL 的響應時間。
對於MySQL來講,減小排序有多種辦法,好比:
上面誤區中提到的經過利用索引來排序的方式進行優化
減小參與排序的記錄條數
非必要不對數據進行排序
…
3.儘可能避免 select *
不少人看到這一點後以爲比較難理解,上面不是在誤區中剛剛說 select 子句中字段的多少並不會影響到讀取的數據嗎?
是的,大多數時候並不會影響到 IO 量,可是當咱們還存在 order by 操做的時候,select 子句中的字段多少會在很大程度上影響到咱們的排序效率,這一點能夠經過我以前一篇介紹 MySQL ORDER BY 的實現分析的文章中有較爲詳細的介紹。
此外,上面誤區中不是也說了,只是大多數時候是不會影響到 IO 量,當咱們的查詢結果僅僅只須要在索引中就能找到的時候,仍是會極大減小 IO 量的。
4.儘可能用 join 代替子查詢
雖然 Join 性能並不佳,可是和 MySQL 的子查詢比起來仍是有很是大的性能優點。MySQL 的子查詢執行計劃一直存在較大的問題,雖然這個問題已經存在多年,可是到目前已經發布的全部穩定版本中都廣泛存在,一直沒有太大改善。雖然官方也在很早就認可這一問題,而且承諾儘快解決,可是至少到目前爲止咱們尚未看到哪個版本較好的解決了這一問題。
5.儘可能少 or
當 where 子句中存在多個條件以「或」並存的時候,MySQL 的優化器並無很好的解決其執行計劃優化問題,再加上 MySQL 特有的 SQL 與 Storage 分層架構方式,形成了其性能比較低下,不少時候使用 union all 或者是union(必要的時候)的方式來代替「or」會獲得更好的效果。
6.儘可能用 union all 代替 union
union 和 union all 的差別主要是前者須要將兩個(或者多個)結果集合並後再進行惟一性過濾操做,這就會涉及到排序,增長大量的 CPU 運算,加大資源消耗及延遲。因此當咱們能夠確認不可能出現重複結果集或者不在意重複結果集的時候,儘可能使用 union all 而不是 union。
7.儘可能早過濾
這一優化策略其實最多見於索引的優化設計中(將過濾性更好的字段放得更靠前)。
在 SQL 編寫中一樣可使用這一原則來優化一些 Join 的 SQL。好比咱們在多個表進行分頁數據查詢的時候,咱們最好是可以在一個表上先過濾好數據分好頁,而後再用分好頁的結果集與另外的表 Join,這樣能夠儘量多的減小沒必要要的 IO 操做,大大節省 IO 操做所消耗的時間。
8.避免類型轉換
這裏所說的「類型轉換」是指 where 子句中出現 column 字段的類型和傳入的參數類型不一致的時候發生的類型轉換:
人爲在column_name 上經過轉換函數進行轉換
直接致使 MySQL(實際上其餘數據庫也會有一樣的問題)沒法使用索引,若是非要轉換,應該在傳入的參數上進行轉換
由數據庫本身進行轉換
若是咱們傳入的數據類型和字段類型不一致,同時咱們又沒有作任何類型轉換處理,MySQL 可能會本身對咱們的數據進行類型轉換操做,也可能不進行處理而交由存儲引擎去處理,這樣一來,就會出現索引沒法使用的狀況而形成執行計劃問題。
9.優先優化高併發的 SQL,而不是執行頻率低某些「大」SQL
對於破壞性來講,高併發的 SQL 老是會比低頻率的來得大,由於高併發的 SQL 一旦出現問題,甚至不會給咱們任何喘息的機會就會將系統壓跨。而對於一些雖然須要消耗大量 IO 並且響應很慢的 SQL,因爲頻率低,即便遇到,最多就是讓整個系統響應慢一點,但至少可能撐一下子,讓咱們有緩衝的機會。
10.從全局出發優化,而不是片面調整
SQL 優化不能是單獨針對某一個進行,而應充分考慮系統中全部的 SQL,尤爲是在經過調整索引優化 SQL 的執行計劃的時候,千萬不能顧此失彼,因小失大。
11.儘量對每一條運行在數據庫中的SQL進行 explain
優化 SQL,須要作到心中有數,知道 SQL 的執行計劃才能判斷是否有優化餘地,才能判斷是否存在執行計劃問題。在對數據庫中運行的 SQL 進行了一段時間的優化以後,很明顯的問題 SQL 可能已經不多了,大多都須要去發掘,這時候就須要進行大量的 explain 操做收集執行計劃,並判斷是否須要進行優化。