MariaDB數據庫存儲引擎、索引和EXPLAIN

                      MariaDB數據庫存儲引擎、索引和EXPLAIN

----------------------------------------------------------------------------------------------------------------------------------------

1、存儲引擎

MySQL5.5.5前默認的數據庫引擎爲MyISAM,之後的是InnoDB,現在新版本是InnoDB的加強版XtraDB

(1)MyIsam與InnoDB的區別


MyISAM

InnoDB

最大存儲

256TB

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之間未完成的數據

    <4>MVCC:多版本併發控制機制

(2)存儲引擎特定

<1>MyISAM特點:

不支持事務

表級鎖定

讀寫相互阻塞,寫入不能讀,讀時不能寫

只緩存索引

不支持外鍵約束

不支持聚簇索引

讀取數據較快,佔用資源較少

不支持MVCC(多版本併發控制機制)高併發

崩潰恢復性較差

MySQL5.5.5前默認的數據庫引擎

<2>適用場景:只讀(或者寫較少)、表較小(可以接受長時間進行修復操作)

<3>MyISAM引擎文件:

tbl_name.frm: 表格式定義

tbl_name.MYD: 數據文件

tbl_name.MYI: 索引文件

<4>InnoDb引擎特點

行級鎖

支持事務,適合處理大量短期事務

讀寫阻塞與事務隔離級別相關

可緩存數據和索引

支持聚簇索引

崩潰恢復性更好

支持MVCC高併發

從MySQL5.5後支持全文索引

從MySQL5.5.5開始爲默認的數據庫引擎

<5>InnoDB引擎下,建議修改/etc/my.cnf,在[mysqld]下添加defaults-storage-engine=INNODB和innodb-file-per-table,否則所有InnoDB表的數據和索引放置於同一個表空間中image.png

設置好後從此之後新建的數據庫都將數據文件和表格式定義分開存放

數據文件(存儲數據和索引):tb_name.ibd,表格式定義:tb_name.frm

2、其它存儲引擎

(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”引擎,它什麼都不做。可以使用此引擎創建表,但不能將數據存儲在其中或從中檢索。目的是作爲例子來說明如何開始編寫新的存儲引擎

3、MariaDB支持的其它存儲引擎:OQGraph、SphinxSE、TokuDB、Cassandra、CONNECT、SQUENCE

4、管理存儲引擎

(1)查看庫中所有表使用的存儲引擎

    Show table status from db_name;

(2)查看庫中指定表的存儲引擎

    show table status like ' tb_name';

    show create table tb_name;

(3)設置表的存儲引擎:

    CREATE TABLE tb_name(... ) ENGINE=InnoDB;

    ALTER TABLE tb_nameENGINE=InnoDB;

(4)查看引擎

    SHOW ENGINES;

5、MySQL中的系統數據庫

(1)mysql數據庫:mysql的核心數據庫,類似於sql server中負責存儲數據庫的用戶、權限設置、關鍵字等mysql自己需要使用的控制和管理信息

(2)performance_schema:mysql 5.5開始新怎的數據庫,主要用於收集數據庫服務器性能參數,庫裏表的存儲引擎均爲performance_schema,用戶不能創建存儲引擎爲performance_schema的表

(3)information_schema數據庫:mysql 5.0之後產生的,一個虛擬數據庫,物理上並不存在。提供了訪問數據庫元數據的方式,即數據的數據。

6、服務器配置

(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/

(2)服務器系統變量:分全局和會話兩種

(3)服務器狀態變量:分全局和會話兩種

(4)獲取運行中的mysql進程使用各服務器參數及其值

進入數據庫輸入SQL語句

SHOW GLOBAL VARIABLES;

SHOW [SESSION] VARIABLES;image.png

      (5)設置服務器選項方法:

<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;

(7)修改會話變量:

    mysql> SET [SESSION] system_var_name=value;

    mysql> SET @@[session.]system_var_name=value;

(8)狀態變量(只讀):用於保存mysqld運行中的統計數據的變量,不可更改

    mysql> SHOW GLOBAL STATUS;

    mysql> SHOW [SESSION] STATUS;

注意:

(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 '...%';,不可更改,只讀

7、服務器變量SQL_MODE

(1)SQL_MODE:對其設置可以完成一些約束檢查的工作,可分別進行全局的設置或者當前會話的設置

(2)開啓方式:SET SQL_MODE='traditional',加上global對全局設置,不加global對當前會話設置

(3)常見MODE

<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:將||視爲連接操作符而非“或運算符”

8、查詢緩存

(1)查詢先看是否有查詢緩存,如果有將直接顯示緩存,加快了速度。由於查詢緩存運用了哈希運算,因此如果想要引用查詢緩存,SQL語句使用需要與在查詢緩存中的SQL語句一模一樣,甚至大小寫一致

(2)哪些查詢可能不會被緩存

<1>查詢語句中加了SQL_NO_CACHE參數

<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時,所有查詢語句都不能緩存

(3)查詢服務器相關變量

show variables like 'query_cache%';image.png

<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;

    查詢變量或者選項示例:

image.png


9、優化查詢緩存

image.png

10、查詢緩存

查詢緩存相關的狀態變量: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 數量image.png

由此可以得出命中率和內存使用率估算:

(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%

11、InnoDB存儲引擎

(1)InnoDB存儲引擎的緩衝池:通常InnoDB存儲引擎緩衝池的命中不應該小於99%

(2)查看相關狀態變量:只讀

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: 從緩衝池中讀取頁次數

<5>Innodb_data_read: 總共讀入的字節數

<6>Innodb_data_reads: 發起讀取請求的次數,每次讀取可能需要讀取多個頁

12、索引

(1)索引是特殊結構:定義在查找時作爲查找的字段

(2)索引實現基於存儲引擎

(3)優點:

<1>索引可以降低服務需要掃描的數據量,減少了IO次數

<2>索引可以幫助服務器避免排序和使用臨時表

<3>索引可以幫助將隨機IO轉爲順序IO

(4)缺點:

<1>佔用額外空間,影響插入速度,不過對於具有大量查詢需求的數據庫是值得的

<2>數據庫發生變化,索引也需要更新

(5)索引類型

<1>B-TREE(唸作B樹)、B+ TREE、HASH、R TREE

<2>聚簇(集)索引、非聚簇索引:數據和索引是否存儲在一起

聚集索引:數據和索引放在一起,InnoDB

非聚集索引:數據和索引分離放置,MyISAM

<3>主鍵索引、二級(輔助)索引

主鍵索引:索引的排列次序和數據在磁盤上的排列次序是一致的

二級索引:利用唯一鍵建立索引

<4>稠密索引、稀疏索引:是否索引了每一個數據項

稠密索引:索引存放了每個數據項

稀疏索引:索引存放了部分數據項

<5>簡單索引、組合索引

左前綴索引:取前面的字符做索引

覆蓋索引:從索引中即可取出要查詢的數據,性能高

(6)B-TREE,平衡樹,balanced treeimage.png

(7)B+TREE,比B-TREE穩定image.png

<1>可以使用B+Tree索引的查詢類型:

全值匹配:精確所有索引列,如:姓wang,名xiaochun,年齡30

匹配最左前綴:即只使用索引的第一列,如:姓wang

匹配列前綴:只匹配一列值開頭部分,如:姓以w開頭的

匹配範圍值:如:姓ma和姓wang之間

精確匹配某一列並範圍匹配另一列:如:姓wang,名以x開頭的

只訪問索引的查詢

<2>B+Tree索引的限制:

如不從最左列開始,則無法使用索引,如:查找名爲xiaochun,或姓爲g結尾

不能跳過索引中的列:如:查找姓wang,年齡30的,只能使用索引第一列

如果查詢中某個列是爲範圍查詢,那麼其右側的列都無法再使用索引:如:姓wang,名x%,年齡30,只能利用姓和名上面的索引

<3>特別提示:

索引列的順序和查詢語句的寫法應相匹配,才能更好的利用索引

爲優化性能,可能需要針對相同的列但順序不同創建不同的索引來滿足不同類型的查詢需求

(8)Hash索引

<1>Hash索引:基於哈希表實現,基於哈希表實現,只有精確匹配索引中的所有列的查詢纔有效,索引自身只存儲索引列對應的哈希值和數據指針,索引結構緊湊,查詢性能好

<2>Memory存儲引擎支持顯式hash索引,InnoDB和MyISAM存儲引擎不支持

<3>適用場景:只支持等值比較查詢,包括=, <=>, IN()

<4>不適合使用hash索引的場景

不適用於順序查詢:索引存儲順序的不是值的順序

不支持模糊匹配

不支持範圍查詢

不支持部分索引列匹配查找:如A,B列索引,只查詢A列索引無效

(9)地理空間索引( Geospatial indexing)

MyISAM支持地理空間索引,可以使用任意維度組合查詢,使用特有的函數訪問,常用於做地理存儲存儲,使用不多

InnoDB從MySQL5.7後開始支持

(10)全文索引

在文本中查找關鍵詞,而不是直接比較索引中的值,類似搜索引擎

InnoDB從MySQL5.6後開始支持

(11)冗餘和重複索引:

冗餘索引:(A),(A,B),比如說有了idx_name_age建立的符合索引,此時再有name或者age的索引,name或者age就是冗餘索引

重複索引:已經有索引,再次建立索引

(12)索引優化策略:

<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>選擇合適的索引列順序:無排序和分組時,將選擇性最高放左側 

13、管理索引

(1)創建索引:

CREATE INDEX index_name ON tbl_name (index_col_name[(length)],...);

help CREATE INDEX;

(2)索引的使用:

SELECT ... WHERE 字符(加索引的字段) { like | in | = ...};

(3)刪除索引:

DROP INDEX index_name ON tbl_name;

(4)查看索引:

SHOW INDEXES FROM [db_name.]tbl_name;

(5)優化表空間:

OPTIMIZE TABLE tb_name;,當索引建立後長時間不用

(6)查看索引的使用

SET GLOBAL userstat=1;

SHOW INDEX_STATISTICS;

示例:現有一存儲過程,可以實現建立99999個用戶id、name、age的表格image.png

之後mysql DB < FILE.sql,進入數據庫調用call protestlog,產生數據表如圖

image.png

共有99999條這樣的記錄,現在我們開始示例索引image.png

利用索引查詢和不利用索引查詢image.png

刪除索引

image.png

建立複合索引

image.png

14、索引優化建議

(1)只要列中含有NULL值,就最好不要在此例設置索引,複合索引如果有NULL值,此列在使用時也不會使用索引

(2)儘量使用短索引,如果可以,應該制定一個前綴長度

(3)對於經常在where子句使用的列,最好設置索引

(4)對於有多個列where或者order by子句,應該建立複合索引

(5)對於like語句,以%或者‘-’開頭的不會使用索引,以%結尾會使用索引,索引使用禁止使用like '%...'或者'%...%',只允許'...%'的形式

(6)儘量不要在列上進行運算(函數操作和表達式操作)

(7)儘量不要使用not in和<、>操作

15、SQL語句性能優化

(1)查詢時,能不要*就不用*,儘量寫全字段名

(2)大部分情況連接效率遠大於子查詢

(3)多表連接時,儘量小表驅動大表,即小表 join 大表

(4)在有大量記錄的表分頁時使用limit

(5)對於經常使用的查詢,可以開啓緩存

(6)多使用explain和profile分析查詢語句

(7)查看慢查詢日誌,找出執行時間長的sql語句優化

16、EXPLAIN

通過EXPLAIN來分析索引的有效性

(1)用法:EXPLAIN SELECT 從句

(2)id: 當前查詢語句中,每個SELECT語句的編號

複雜類型的查詢有三種:

簡單子查詢

用於FROM中的子查詢

聯合查詢:UNION

注意:UNION查詢的分析結果會出現一個額外匿名臨時表

(3)select_type:

簡單查詢爲SIMPLE

複雜查詢:

SUBQUERY 簡單子查詢

PRIMARY 最外面的SELECT

DERIVED 用於FROM中的子查詢

UNION UNION語句的第一個之後的SELECT語句

UNION RESULT 匿名臨時表

(4)table:SELECT語句關聯到的表

(5)type:關聯類型或訪問類型,即MySQL決定的如何去查詢表中的行的方式,以下順序,性能從低到高

<1>ALL: 全表掃描

<2>index:根據索引的次序進行全表掃描;如果在Extra列出現“Using index”表示了使用覆蓋索引,而非全表掃描

<3>range:有範圍限制的根據索引實現範圍掃描;掃描位置始於索引中的某一點,結束於另一點

<4>ref: 根據索引返回表中匹配某單個值的所有行

<5>eq_ref:僅返回一個行,但與需要額外與某個參考值做比較

<6>const, system: 直接返回單個行

(6)possible_keys:查詢可能會用到的索引

(7)key: 查詢中使用到的索引

(8)key_len: 在索引使用的字節數

(9)ref: 在利用key字段所表示的索引完成查詢時所用的列或某常量值

(10)rows:MySQL估計爲找所有的目標行而需要讀取的行數

(11)Extra:額外信息

Using index:MySQL將會使用覆蓋索引,以避免訪問表

Using where:MySQL服務器將在存儲引擎檢索後,再進行一次過濾

Using temporary:MySQL對結果排序時會使用臨時表

Using filesort:對結果使用一個外部索引排序

示例

image.png

出現黃字情況possible_keys有值,但key爲NULL


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章