MariaDB基礎(二)
介紹關於MariaDB的如下知識點:
1. 查詢緩存
2. 索引
3. EXPLAIN
1.查詢緩存:
1)什麼是緩存?
緩存就是數據交換的緩衝區,即Cache,存放在內存中;
2)查詢緩存的數據以何種形式存在?
查詢緩存的數據以鍵值對(key/value)的形式存在;
key : 查詢語句的哈希值(哈希值可理解爲數據的×××,用於驗證數據來源的真實性)
value : 查詢語句的查詢結果
3)緩存命中的標準:
將查詢語句的哈希值與數據的源哈希值做比較,相同則命中,反之則未命中;
4)什麼樣的查詢結果不可緩存?
1. 要查詢的數據庫中包含敏感信息,如MySQL數據庫中的各系統表;
2. 查詢語句中包含用戶自定義的函數或變量;
3. 存儲函數;
4. 對於臨時表發起的查詢請求;
5. 包含列級別授權的查詢;
6. 有着不確定值得MySQL內建函數;如:NOW(),CURRENT_DATE()等;
5) 與查詢緩存相關得服務器變量
MariaDB [(none)]> show global variables like 'query_cache%'; +------------------------------+---------+ | Variable_name | Value | +------------------------------+---------+ | query_cache_limit | 1048576| | query_cache_min_res_unit | 4096 | | query_cache_size | 0 | | query_cache_strip_comments | OFF | | query_cache_type | ON | | query_cache_wlock_invalidate| OFF | +------------------------------+---------+ 1.query_cache_limit:查詢緩存限制 能夠緩存的最大結果的字節數上限(單語句結果集的上限) 注意:在使用select查詢語句時,儘量避免避免“select * ” 儘可能使用where或having子句,是結果儘可能精確; 2.query_cache_min_res_unit:查詢緩存的最小分配單元 功能:可有效避免內存碎片 注意:較大的變量值可能會造成內存空間的浪費; 較小的變量值可能減少內存空間浪費,但會導致頻繁的內存 分配和回收操作,長期會造成內存碎片; 3.query_cache_size:查詢緩存大小 查詢緩存申請的在內存空間的空間大小,單位爲字節, 大小需是1024的整數倍; 示例: MariaDB [(none)]> select 10*1024*1024; +--------------+ | 10*1024*1024| +--------------+ | 10485760 | +--------------+ MariaDB [(none)]> set @@global.query_cache_size=10485760; 4.query_cache_strip_comments 用於控制是否去掉SQL查詢語句中的註釋部分之後再作爲key存入查詢緩存; 默認值爲“OFF”,如果啓用,插入查詢緩存的查詢語句是不帶有註釋信息的; 5.query_cache_type:緩存功能開啓與否的開關 ON:啓用;僅不緩存"SQL_NO_CACHE"參數的查詢結果; OFF:停用; DEMAND:按需緩存;默認不緩存,僅緩存"SQL_CACHE"參數的查詢結果; 6.query_cache_wlock_invalidate:查詢緩存寫鎖無效開關 功能:如果某會話對某表施加了寫鎖,是否可以從緩存中查詢並返回查詢結果; OFF: 可以 ON: 不可以
6)與查詢緩存相關的服務器狀態參數
MariaDB [(none)]> show global status like 'Qcache%'; +-------------------------+----------+ | Variable_name | Value | +-------------------------+----------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 10468296| | Qcache_hits | 0 | | Qcache_inserts | 0 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 0 | | Qcache_queries_in_cache| 0 | | Qcache_total_blocks | 1 | +-------------------------+----------+ 1.Qcache_free_blocks: 查詢緩存空閒塊 查看目前緩存中有多少個剩餘空閒塊 若該數值過大,說明內存碎片過多 2.Qcache_free_memory: 查詢緩存空閒內存空間 如果該值太小,且剩餘塊太多,則內存碎片多; 如果該值太小,且剩餘塊不多,則說明分配查詢緩存的內存空間剛好或偏小; 如果該值較大,分配的查詢緩存的內存空間太多,應進行相應調整; 一旦調整了緩存大小,則其中存放的查詢結果會立即被清除; 3.Qcache_hits: 查詢緩存命中數 4.Qcache_inserts: 表示未命中的而後經過處理將查詢結果添加至查詢緩存的查詢請求的數量; 數值越大,則證明查詢緩存效果越不理想; 可以通過規範書寫查詢請求的SQL語句減少此類查詢請求的數量; 注意:如果查詢緩存中確實沒有對應查詢語句的查詢緩存,此數值的增加也是正常現象; 5.Qcache_lowmem_prunes:查詢緩存低內存修剪 該參數記錄了有多少條查詢請求是因爲內存空間不足而基於LRU算法移出緩存的; 如果該數值多大,則表示爲查詢緩存分配的內存空間太小; 6.Qcache_not_cached:查詢請求未被緩存 取決於query_cache_type變量的設置的作用下,沒有被緩存的查詢請求的數量; 7.Qcache_queries_in_cache:當前查詢緩存中緩存的查詢請求的結果的數量; 8.Qcache_total_blocks:當前查詢緩存中總計分配了多少個block
示例:修改查詢緩存相關服務器變量,查詢數據後,查看服務器狀態參數變化:
設置前狀態參數:
MariaDB [(none)]> show global status like 'Qcache%'; +-------------------------+-------+ | Variable_name | Value| +-------------------------+-------+ | Qcache_free_blocks | 0 | | Qcache_free_memory | 0 | | Qcache_hits | 0 | | Qcache_inserts | 0 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 0 | | Qcache_queries_in_cache| 0 | | Qcache_total_blocks | 0 | +-------------------------+-------+
設置query_cache_size爲10485760(該值需爲1024的整數倍)
MariaDB [(none)]> select 10*1024*1024; +--------------+ | 10*1024*1024| +--------------+ | 10485760 | +--------------+ MariaDB [(none)]> set @@global.query_cache_size=10485760; MariaDB [(none)]> show global variables like 'query_cache%'; +------------------------------+----------+ | Variable_name | Value | +------------------------------+----------+ | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 10485760| | query_cache_strip_comments | OFF | | query_cache_type | ON | | query_cache_wlock_invalidate| OFF | +------------------------------+----------+
查看此時狀態參數:開闢了一個空閒的塊,緩存剩餘爲10468296
MariaDB [(none)]> show global status like 'Qcache%'; +-------------------------+----------+ | Variable_name | Value | +-------------------------+----------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 10468296| | Qcache_hits | 0 | | Qcache_inserts | 0 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 0 | | Qcache_queries_in_cache| 0 | | Qcache_total_blocks | 1 | +-------------------------+----------+
使用名爲hellodb的數據庫,用select語句查看庫中students表的信息,查看狀態參數變化
如下:緩存剩餘空間變爲10466128
因爲第一次請求所以沒有命中緩存,即Qcache_hits=0;
因爲有一個select請求,所以將該請求列入緩存,即Qcache_inserts=1;
未緩存爲1,即Qcache_not_cached=1
請求數爲1,即Qcache_queries_in_cache=1
分配塊數爲4,即Qcache_total_blocks=4
MariaDB [(none)]> use hellodb; MariaDB [hellodb]> select * from students; MariaDB [hellodb]> show global status like 'Qcache%'; +-------------------------+----------+ | Variable_name | Value | +-------------------------+----------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 10466128| | Qcache_hits | 0 | | Qcache_inserts | 1 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 1 | | Qcache_queries_in_cache| 1 | | Qcache_total_blocks | 4 | +-------------------------+----------+
再次請求查看:
緩存空間變小
命中數爲2, 即Qcache_hits=2
(因爲之前相同的select請求被列入緩存,所以接下來兩次請求都命中)
MariaDB [hellodb]> select * from students; MariaDB [hellodb]> select * from students; MariaDB [hellodb]> show global status like 'Qcache%'; +-------------------------+----------+ | Variable_name | Value | +-------------------------+----------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 10466128| | Qcache_hits | 2 | | Qcache_inserts | 1 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 1 | | Qcache_queries_in_cache| 1 | | Qcache_total_blocks | 4 | +-------------------------+----------+
7) 如何優化緩存:
1:儘可能的批量寫入(構建自定義過程,啓用事務),儘量減少多次的單寫入操作;
2:緩存空間不宜設置過大,如果大量緩存同時失效,會使MySQL的執行引擎壓力過大,可能導致服務器假死;
3. 必要時,必須使用SQL_CACHE和SQL_NO_CACHE等SELECT語句中的參數手動控制緩存存入與否;
4. 對於密集型寫操作應用場景來說,禁用緩存功能可能提升服務器性能;
2. 索引
1)什麼是索引?
指的是表中的數據子集;
即:將表中的某個或某些字段中的數據提取出來,另存爲一個用一個特定數據結構進行組織的數據;
2)索引的功能
加速查詢操作
3) 索引的類型
FULLTEXT,SPACIAL,B+ TREE,HASH
B+ TREE索引:
順序存儲,所有的索引數據都放在葉節點上,並且每個葉節點都有順序訪問指針,
以此指針指向相鄰的葉子節點,可提高區間數據的查詢效率;
最左前綴索引:適用於高效的範圍類數據查詢;
適用的場景:
全鍵值匹配:精確匹配某個值;
select .... where Name='zhangsan';
左前綴匹配:只精確到數據起始位置的一部分;
select ... where Name like 'zhangsan%';
區間數據的連續數值匹配:通常用於BETWEEN...AND...環境中;
select ... where Age between 20 and 30;
區間數據的離散值匹配:通常用於IN列表環境或OR列表環境;也是精確匹配;
select ... where StuID in (1,2,4);
精確匹配左列,範圍匹配右側其它列:
select ... where StuID > 10 and Name like 'a%';
對於覆蓋索引的查詢請求;
不適用的場景:
如果查詢條件不是精確從最左側列開始的,索引無效;
如:對StuID字段做了索引,select ... where Name like 'a%' and StuID >10;
如果索引了多列,若跳過了索引中的某列,則索引無效:
如:對StuID,Name,Age做索引,select ... where StuID>10 and Age>20;
如果索引了多列,且在查詢語句中某個列做範圍匹配,則右側列不再使用索引優化查詢:
HASH索引:基於HASH表實現的索引;
非常適用於值的精確匹配的查詢請求;
適用場景:
只支持等值比較查詢:
如:=,IN(),<=>(NULL safe equal) ;
不適用的場景:
所有的非精確值的比較查詢;
注意:
1.在InnoDB存儲引擎中,創建索引時,只能顯式使用“BTREE”索引;
2.索引中的數據來源於數據表,但數據結構與源數據可能有很大差異;
4)索引的查詢優點:
1. 減少需要掃描的數據總量,減少IO次數
2. 避免對掃描的數據進行再次排序;
3. 避免生成和使用臨時表;
4. 將隨機IO轉換爲順序IO;
5) 定義索引的一般性規則:
1.選擇用於索引的數據類型;
越小的數據類型越適於做索引;例如int和char
越簡單的數據類型越適於做索引;例如 char 和varchar
儘量避免該字段中出現“NULL”值;如果必須要使用空值,建議使用“0”或一個空的字符串
或某個認可的特殊值來代替“NULL”值;
2.選擇主鍵的類型:
優先選擇整型;
整型數據可以更快速被處理,且可以使用AUTO_INCREMENT修飾符避免重複數據;
儘量避免使用字符型;
存儲字符型數據需要消耗更多空間,處理字符型數據需要消耗更多的CPU和內存資源,處理速度較慢;
可能導致頁面分裂,隨機IO等問題;
3. EXPLAIN
查看幫助文檔:
MariaDB [hellodb]> help explain;
格式:explain_type: EXTENDED| PARTITIONS Or: EXPLAIN tbl_name
示例:
MariaDB [hellodb]> explain select * from students where StuID<30\G; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: students type: range possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: NULL rows: 26 Extra: Using where 1.id:當前的查詢語句中,各個select語句的編號; 2.select_type:查詢類型 簡單查詢:SIMPLE 複雜查詢: 簡單的子查詢(用於where子句中的子查詢):SUBQUERY 用於FROM語句中的子查詢:DERIVED 聯合查詢中的第一個查詢:PRIMARY; 聯合查詢中其它的查詢:UNION 聯合查詢時生成的臨時表查詢:UNION RESULT 3.table: 當前的查詢語句所針對的表; 4.type: 關聯類型,或稱訪問類型,也可理解爲MySQL是如何查詢表中的行; 1) ALL:全表掃描,MySQL將遍歷全表找到可以匹配的行; 2) index:全表掃描,與ALL不同的是index類型只是遍歷索引樹; 3) range:索引範圍掃描,對索引的掃描從某一個點開始,返回匹配值域的行; 通常可以基於指定的索引,where子句中使用IN列表,BETWEEN...AND....或帶有“=”,“>","<"的查詢; 4) ref: 使用非唯一索引掃描或使用唯一索引的做左前綴掃描,返回匹配某個單獨值得行; 5) eq_ref: 類似ref,區別是使用唯一索引,對於每一個索引鍵值,表中都只有一條記錄匹配; 無論是單表查詢還是多表查詢,都使用主鍵或唯一鍵索引作爲關聯條件; 6) const,system: 當MySQL對查詢部分進行優化,並轉換爲一個常量;使用const類型 system類型是一個const類型得特例,當要查詢得表是一行時,使用system類型; 7) NULL : MySQL在優化過程中分解查詢語句,執行時不用訪問表或索引; 5.possible_keys: 爲了執行查詢語句,MySQL可能使用哪個索引在表中查找到記錄; 如果查詢所涉及到的字段上,如果存在索引,則該索引被列出,但不一定被查詢使用; 6. key: 顯示MySQL數據庫在查詢過程中實際使用到的索引;如果查詢過程沒有用到任何索引,則此處顯示“NULL”; 7. key_len: 表示索引中可以被引用的最大字節數;可通過該列計算查詢中使用的索引的長度; 注意:key_len顯示的值通常爲索引字段的最大可能長度,並非實際使用長度,因此key_len是根據表定義時 指定的字段長度計算得到的,並不是在表中通過通過檢索數據得到的; 8. ref: 在利用key字段所顯示的索引完成查詢操作時所引用的列或常量值;若果都沒有則顯示爲NULL; 9. rows: 表示MySQL根據表統計信息及索引選用的情況,估算的本次檢索所需要查找所有記錄的過程中需要讀取表的行數; 10.Extra:額外信息,或稱擴展信息; Using where: 表示MySQL服務器將在存儲引擎檢索後再次進行條件過濾;在許多的where條件裏涉及到索引中的列 並且當MySQL讀取該索引時就可被存儲引擎檢索; Using index: 使用了覆蓋索引進行檢索; Using temporary:在查詢過程中使用了臨時表存放查詢結果集; Using filesort: MySQL中無法利用索引完成的排序操作就稱爲“文件排序”; Using join buffer: 強調了在獲取連接條件時沒有使用到索引,且需要連接緩衝區來存儲中間結果; 如果出現了該值,需要根據查詢的具體情況適當的添加索引以提示查詢性能; Impossible where:若該值出現,則意味着在查詢時沒有發現符合條件的行; Select tables optimized away: 該值意味着僅通過使用索引,來進行查詢, 但是優化器可能從聚合函數的結果中給出一個可行優化方案; 11.filtered:從可選的行中再次過濾之後選擇出最終的查詢結果的比值;即從多少行中過濾選擇出多少行的比值;