MariaDB數據庫存儲引擎、索引和EXPLAINhtml
----------------------------------------------------------------------------------------------------------------------------------------mysql
MySQL5.5.5前默認的數據庫引擎爲MyISAM,以後的是InnoDB,如今新版本是InnoDB的增強版XtraDB數據庫
MyISAM安全 |
InnoDB性能優化 |
|
最大存儲服務器 |
256TBsession |
64TB併發 |
事務 |
N |
Y |
鎖 |
表鎖 |
行鎖 |
MVCC |
N |
Y |
B-TREE |
Y |
Y |
全文索引 |
N |
Y |
聚簇索引 |
N |
Y |
數據緩存 |
N |
Y |
索引緩存 |
Y |
Y |
<1>事務:多種操做的集合。多會話訪問數據庫時,每個操做都會有一個ID,之間互不干擾。假設A在數據庫的某張表中有先插入、再刪除的操做,操做同時B在查詢這張表,那麼B查詢到的結果是A插入未刪時的數據仍是A已經刪除的操做?其實當A作插入insert操做時,數據庫會自動給該動做分配一個ID,作刪除的操做時候回再分配一個ID,且後面操做的ID大於簽名操做的ID。若是B的查詢操做ID位於A的插入以後,刪除以前,那麼B查詢到的就是A在insert後的結果,delete以前的結果
Ainsert=10,Adelete=20,Bselect=15,此時B能夠查到A在insert的結果,查詢不到A的delete後的結果。
<2>鎖:表鎖:鎖的動做是對整個表上鎖,上鎖後其餘用戶不得訪問讀寫
<3>髒數據:事務過程當中尚未結束完的數據,好比說剛纔說的A在insert和delete之間未完成的數據
<2>適用場景:只讀(或者寫較少)、表較小(能夠接受長時間進行修復操做)
<5>InnoDB引擎下,建議修改/etc/my.cnf,在[mysqld]下添加defaults-storage-engine=INNODB和innodb-file-per-table,不然全部InnoDB表的數據和索引放置於同一個表空間中
設置好後今後以後新建的數據庫都將數據文件和表格式定義分開存放
數據文件(存儲數據和索引):tb_name.ibd,表格式定義:tb_name.frm
(1)Performance_Schema:Performance_Schema數據庫
(2)Memory :將全部數據存儲在RAM中,以便在須要快速查找參考和其餘相似數據的環境中進行快速訪問。適用存放臨時數據。引擎之前被稱爲HEAP引擎
(3)MRG_MyISAM:使MySQL DBA或開發人員可以對一系列相同的MyISAM表進行邏輯分組,並將它們做爲一個對象引用。適用於VLDB(Very Large Data Base)環境,如數據倉庫
(4)Archive :爲存儲和檢索大量不多參考的存檔或安全審覈信息,只支持SELECT和INSERT操做;支持行級鎖和專用緩存區
(5)Federated聯合:用於訪問其它遠程MySQL服務器一個代理,它經過建立一個到遠程MySQL服務器的客戶端鏈接,並將查詢傳輸到遠程服務器執行,然後完成數據存取,提供連接單獨MySQL服務器的能力,以便從多個物理服務器建立一個邏輯數據庫。很是適合分佈式或數據集市環境
(6)BDB:可替代InnoDB的事務引擎,支持COMMIT、ROLLBACK和其餘事務特性
(7)Cluster/NDB:MySQL的簇式數據庫引擎,尤爲適合於具備高性能查找要求的應用程序,這類查找需求還要求具備最高的正常工做時間和可用性
(8)CSV:CSV存儲引擎使用逗號分隔值格式將數據存儲在文本文件中。可使用CSV引擎以CSV格式導入和導出其餘軟件和應用程序之間的數據交換
(9)BLACKHOLE :黑洞存儲引擎接受但不存儲數據,檢索老是返回一個空集。該功能可用於分佈式數據庫設計,數據自動複製,但不是本地存儲
(10)example:「stub」引擎,它什麼都不作。可使用此引擎建立表,但不能將數據存儲在其中或從中檢索。目的是做爲例子來講明如何開始編寫新的存儲引擎
三、MariaDB支持的其它存儲引擎:OQGraph、SphinxSE、TokuDB、Cassandra、CONNECT、SQUENCE
Show table status from db_name;
show table status like ' tb_name';
CREATE TABLE tb_name(... ) ENGINE=InnoDB;
ALTER TABLE tb_nameENGINE=InnoDB;
(1)mysql數據庫:mysql的核心數據庫,相似於sql server中負責存儲數據庫的用戶、權限設置、關鍵字等mysql本身須要使用的控制和管理信息
(2)performance_schema:mysql 5.5開始新怎的數據庫,主要用於收集數據庫服務器性能參數,庫裏表的存儲引擎均爲performance_schema,用戶不能建立存儲引擎爲performance_schema的表
(3)information_schema數據庫:mysql 5.0以後產生的,一個虛擬數據庫,物理上並不存在。提供了訪問數據庫元數據的方式,即數據的數據。
(1)mysqld選項,服務器系統變量和服務器狀態變量,在兩個官方網址中查詢是服務器變量仍是服務器選項
https://dev.mysql.com/doc/refman/5.7/en/mysqld-option-tables.html
https://mariadb.com/kb/en/library/full-list-of-mariadb-options-system-and-status-variables/
<1>在命令行中設置./mysqld_safe --skip-name-resolve=1;
<2>在配置文件my.cnf中添加skip_name_resolve=1,避免IP被反向解析爲名字,建議添加此項
(6)修改全局變量:僅對修改後新建立的會話有效;對已經創建的會話無效
mysql> SET GLOBAL system_var_name=value;
mysql> SET @@global.system_var_name=value;
mysql> SET [SESSION] system_var_name=value;
mysql> SET @@[session.]system_var_name=value;
(8)狀態變量(只讀):用於保存mysqld運行中的統計數據的變量,不可更改
(1)有些既是服務器變量,又是服務器選項,好比說--binlog-cacho-size爲選項,但也有binlog_cache_size的變量
(2)當修改變量時用SET [GLOBAL] VARNAME=value做爲修改,用show variables like ' ';查詢,該變量修改後會在重啓後消失,並且變量不支持加入配置文件中。選項的修改能夠直接將該選項放入/etc/my.cnf下的[mysqld],該修改成永久保存。查找是服務器變量仍是服務器選項去剛給的官網網址能夠查找
(3)查詢變量show [global] variables like '...%';
查詢狀態變量show [global] status like '...%';,不可更改,只讀
(1)SQL_MODE:對其設置能夠完成一些約束檢查的工做,可分別進行全局的設置或者當前會話的設置
(2)開啓方式:SET SQL_MODE='traditional',加上global對全局設置,不加global對當前會話設置
<1>NO_AUTO_CREATE_USER:禁止GRANT建立密碼爲空的用戶
<2>NO_ZERO_DATE:在嚴格模式,不容許使用‘0000-00-00’的時間
<3>ONLY_FULL_GROUP_BY:對於GROUP BY分組操做,若是SELECT的字段沒有在分組GROUP BY中存在會認爲這個SQL語句是不合法的
<4>NO_BACKSLASH_ESCAPES:反斜槓\做爲普通字符而非轉義字符
<5>PIPES_AS_CONCAT:將||視爲鏈接操做符而非「或運算符」
(1)查詢先看是否有查詢緩存,若是有將直接顯示緩存,加快了速度。因爲查詢緩存運用了哈希運算,所以若是想要引用查詢緩存,SQL語句使用須要與在查詢緩存中的SQL語句如出一轍,甚至大小寫一致
<2>查詢語句中含有得到值的函數,包含自定義函數,如:NOW()
CURDATE()、GET_LOCK()、RAND()、CONVERT_TZ()等
<3>對系統數據庫的查詢:mysql、information_schema查詢語句中使用SESSION級別變量或存儲過程當中的局部變量
<4>查詢語句中使用了LOCK IN SHARE MODE、FOR UPDATE的語句,查詢語句中相似SELECT …INTO 導出數據的語句
<5>對臨時表的查詢操做;存在警告信息的查詢語句;不涉及任何表或視圖的查詢語句;某用戶只有列級別權限的查詢語句
<6>事務隔離級別爲Serializable時,全部查詢語句都不能緩存
show variables like 'query_cache%';
<1>query_cache_min_res_unit: 查詢緩存中內存塊的最小分配單位,默認4k,較小值會減小浪費,但會致使更頻繁的內存分配操做,較大值會帶來浪費,會致使碎片過多,內存不足
<2>query_cache_limit:單個查詢結果能緩存的最大值,默認爲1M,對於查詢結果過大而沒法緩存的語句,建議使用SQL_NO_CACHE
<3>query_cache_size:查詢緩存總共可用的內存空間;單位字節,必須是1024的整數倍,最小值40KB,低於此值有警報
<4>query_cache_wlock_invalidate:若是某表被其它的會話鎖定,是否仍然能夠從查詢緩存中返回結果,默認值爲OFF,表示能夠在表被其它會話鎖定的場景中繼續從緩存返回數據;ON則表示不容許
<5>query_cache_type: 是否開啓緩存功能,取值爲ON, OFF, DEMAND,當query_cache_type的值爲ON或1時,查詢緩存功能打開,SELECT的結果符合緩存條件即會緩存,顯式指定SQL_NO_CACHE,不予緩存,此爲默認值;當query_cache_type的值爲DEMAND或2時,查詢緩存功能按需進行,顯式指定SQL_CACHE的SELECT語句纔會緩存;其它均不予緩存
注意:以上爲服務器變量,設置時候是SET [GLOBAL] VARNAME=value;
查詢變量或者選項示例:
查詢緩存相關的狀態變量:SHOW GLOBAL STATUS LIKE ‘Qcache%';
(1)Qcache_free_blocks:處於空閒狀態Query Cache中內存Block 數
(2)Qcache_total_blocks:Query Cache 中總Block ,當Qcache_free_blocks相對此值較大時,可能用內存碎片,執行FLUSH QUERY CACHE清理碎片
(3)Qcache_free_memory:處於空閒狀態的Query Cache 內存總量
(4)Qcache_hits:Query Cache 命中次數,好比輸入同一個SQL查詢語句兩次,該記錄會加1,兩次輸入的SQL語句大小必須一致
(5)Qcache_inserts:向Query Cache 中插入新的Query Cache 的次數,即沒有命中的次數
(6)Qcache_lowmem_prunes:0記錄有多少條查詢由於內存不足而被移除出查詢緩存
(7)Qcache_not_cached:沒有被Cache 的SQL 數,包括沒法被Cache 的SQL 以及因爲query_cache_type設置的不會被Cache 的SQL語句,好比select now()輸入後,該記錄會加1
(8)Qcache_queries_in_cache:在Query Cache 中的SQL 數量
由此能夠得出命中率和內存使用率估算:
(1)查詢緩存中內存塊的最小分配單位query_cache_min_res_unit:(query_cache_size-Qcache_free_memory) / Qcache_queries_in_cache
(2)查詢緩存命中率:Qcache_hits/ ( Qcache_hits+ Qcache_inserts) * 100%
(3)查詢緩存內存使用率:(query_cache_size–qcache_free_memory) / query_cache_size* 100%
(1)InnoDB存儲引擎的緩衝池:一般InnoDB存儲引擎緩衝池的命中不該該小於99%
show global status like 'innodb%read%'\G
<1>Innodb_buffer_pool_reads: 表示從物理磁盤讀取頁的次數
<2>Innodb_buffer_pool_read_ahead: 預讀的次數
<3>Innodb_buffer_pool_read_ahead_evicted: 預讀頁,可是沒有讀取就從緩衝池中被替換的頁數量,通常用來判斷預讀的效率
<4>Innodb_buffer_pool_read_requests: 從緩衝池中讀取頁次數
<6>Innodb_data_reads: 發起讀取請求的次數,每次讀取可能須要讀取多個頁
<1>佔用額外空間,影響插入速度,不過對於具備大量查詢需求的數據庫是值得的
<1>B-TREE(念做B樹)、B+ TREE、HASH、R TREE
<2>聚簇(集)索引、非聚簇索引:數據和索引是否存儲在一塊兒
全值匹配:精確全部索引列,如:姓wang,名xiaochun,年齡30
精確匹配某一列並範圍匹配另外一列:如:姓wang,名以x開頭的
如不從最左列開始,則沒法使用索引,如:查找名爲xiaochun,或姓爲g結尾
不能跳過索引中的列:如:查找姓wang,年齡30的,只能使用索引第一列
若是查詢中某個列是爲範圍查詢,那麼其右側的列都沒法再使用索引:如:姓wang,名x%,年齡30,只能利用姓和名上面的索引
爲優化性能,可能須要針對相同的列但順序不一樣建立不一樣的索引來知足不一樣類型的查詢需求
<1>Hash索引:基於哈希表實現,基於哈希表實現,只有精確匹配索引中的全部列的查詢纔有效,索引自身只存儲索引列對應的哈希值和數據指針,索引結構緊湊,查詢性能好
<2>Memory存儲引擎支持顯式hash索引,InnoDB和MyISAM存儲引擎不支持
<3>適用場景:只支持等值比較查詢,包括=, <=>, IN()
不支持部分索引列匹配查找:如A,B列索引,只查詢A列索引無效
(9)地理空間索引( Geospatial indexing)
MyISAM支持地理空間索引,可使用任意維度組合查詢,使用特有的函數訪問,經常使用於作地理存儲存儲,使用很少
冗餘索引:(A),(A,B),好比說有了idx_name_age創建的符合索引,此時再有name或者age的索引,name或者age就是冗餘索引
<1>獨立地使用列:儘可能避免其參與運算,獨立的列指索引列不能是表達式的一部分,也不能是函數的參數,在where條件中,始終將索引列單獨放在比較符號的一側
<2>左前綴索引:構建指定索引字段的左側的字符數,要經過索引選擇性來評估,好比說某個表格name字段定義時候是CHAR(50),但name字段中的全部值按照CHAR(10)的規格就可使用,此時定義name索引時能夠更改name字段字符數,CREATE INDEX idx_name ON tbl_name(name(10));
<3>多列索引:AND操做時更適合使用多列索引,而非爲每一個列建立單獨的索引,查詢語句的where從句中用and鏈接兩個加了索引的字段
<4>選擇合適的索引列順序:無排序和分組時,將選擇性最高放左側
CREATE INDEX index_name ON tbl_name (index_col_name[(length)],...);
SELECT ... WHERE 字符(加索引的字段) { like | in | = ...};
DROP INDEX index_name ON tbl_name;
SHOW INDEXES FROM [db_name.]tbl_name;
OPTIMIZE TABLE tb_name;,當索引創建後長時間不用
示例:現有一存儲過程,能夠實現創建99999個用戶id、name、age的表格
以後mysql DB < FILE.sql,進入數據庫調用call protestlog,產生數據表如圖
利用索引查詢和不利用索引查詢
創建複合索引
(1)只要列中含有NULL值,就最好不要在此例設置索引,複合索引若是有NULL值,此列在使用時也不會使用索引
(4)對於有多個列where或者order by子句,應該創建複合索引
(5)對於like語句,以%或者‘-’開頭的不會使用索引,以%結尾會使用索引,索引使用禁止使用like '%...'或者'%...%',只容許'...%'的形式
(3)多表鏈接時,儘可能小表驅動大表,即小表 join 大表
(5)type:關聯類型或訪問類型,即MySQL決定的如何去查詢表中的行的方式,如下順序,性能從低到高
<2>index:根據索引的次序進行全表掃描;若是在Extra列出現「Using index」表示了使用覆蓋索引,而非全表掃描
<3>range:有範圍限制的根據索引實現範圍掃描;掃描位置始於索引中的某一點,結束於另外一點
<5>eq_ref:僅返回一個行,但與須要額外與某個參考值作比較
(9)ref: 在利用key字段所表示的索引完成查詢時所用的列或某常量值
(10)rows:MySQL估計爲找全部的目標行而須要讀取的行數
Using index:MySQL將會使用覆蓋索引,以免訪問表
Using where:MySQL服務器將在存儲引擎檢索後,再進行一次過濾
Using temporary:MySQL對結果排序時會使用臨時表
出現黃字狀況possible_keys有值,但key爲NULL