MySQL/MariaDB數據庫的查詢緩存優化html
做者:尹正傑 mysql
版權聲明:原創做品,謝絕轉載!不然將追究法律責任。sql
一.MySQL架構數據庫
Connectors(MySQL對外提供的交互接口,API): Connectors組件,是MySQL向外提供的交互組件,如Python,Golang,Java,C++,Php等語言能夠經過該組件來操做SQL語句,實現與SQL的交互。 Connection Pool(鏈接池組件): 負責監聽對客戶端向MySQL Server端的各類請求,接收請求,轉發請求到目標模塊。每一個成功鏈接MySQL Server的客戶請求都會被建立或分配一個線程,該線程負責客戶端與MySQL Server端的通訊,接收客戶端發送的命令,傳遞服務端的結果信息等。 SQL Interface(SQL接口組件): 接收用戶SQL命令,檢查SQL語法是否正確,如DML,DDL和存儲過程等,並將最終結果返回給用戶。 Parser(查詢分析器組件): 首先分析SQL命令語法的合法性,並嘗試將SQL命令分解成數據結構(將SQL指令轉換成二進制格式來執行),若分解失敗,則提示SQL語句不合理。 Optimlzer(優化器組件): 對SQL命令按照標準流程進行優化分析,選擇最佳的查詢路徑。 Caches & Buffers(緩存主件): 緩存和緩衝組件 Pluggable Storage Engines(插件式存儲引擎): 經過插件式存儲引擎訪問真正存儲數據,常見的存儲引擎有MyISAM,InnoDB等。 File system(文件系統): 存儲引擎會幫咱們和操做系統打交道,你們都直到數據持久化存儲的依舊式在本地磁盤上。支持不一樣的文件系統,包括NTFS,EXT2/3/4,NFS,XFS等。 FIle & Logs: 各類各樣的數據庫相關文件,如數據文件,日誌文件等,如Redo(重作),Undo(撤銷)等。 Management Service & Utilities(管理服務組件和工具組件): 提供對MySQL的集成管理,如備份(Backup),恢復(Recovery),安全管理(Security)等
二.查詢的執行路徑緩存
MySQL 整個查詢執行過程,總的來講分爲 5 個步驟 : 1.客戶端向 MySQL 服務器發送一條查詢請求 2.服務器首先檢查查詢緩存,若是命中緩存,則馬上返回存儲在緩存中的結果,不然進入下一階段 3.服務器進行 SQL解析、預處理、再由優化器生成對應的執行計劃 4.MySQL 根據執行計劃,調用存儲引擎的 API來執行查詢 5.將結果返回給客戶端,同時緩存查詢結果
三.查詢緩存 安全
1>.查詢緩存( Query Cache )原理服務器
緩存SELECT操做或預處理查詢的結果集和SQL語句,當有新的SELECT語句或預處理查詢語句請求,先去查詢緩存,判斷是否存在可用的記錄集,判斷標準:與緩存的SQL語句(進行HASH值對比),是否徹底同樣,區分大小寫
2>.查詢緩存( Query Cache )優缺點數據結構
不須要對SQL語句作任何解析和執行,固然語法解析必須經過在先,直接從Query Cache中得到查詢結果,提升查詢性能
查詢緩存的判斷規則,不夠智能,也即提升了查詢緩存的使用門檻,下降其效率;
查詢緩存的使用,會增長檢查和清理Query Cache中記錄集的開銷
3>.哪些查詢可能不會被緩存架構
查詢語句中加了SQL_NO_CACHE參數;
查詢語句中含有得到值的函數,包含自定義函數,如:NOW(),CURDATE(),GET_LOCK(),RAND(),CONVERT_TZ()等;
對系統數據庫的查詢:mysql、information_schema 查詢語句中使用SESSION級別變量或存儲過程當中的局部變量;
查詢語句中使用了LOCK IN SHARE MODE、FOR UPDATE的語句,查詢語句中相似SELECT …INTO 導出數據的語句;
對臨時表的查詢操做;存在警告信息的查詢語句;不涉及任何表或視圖的查詢語句;某用戶只有列級別權限的查詢語句;
事務隔離級別爲Serializable時,全部查詢語句都不能緩存。
4>.查詢緩存相關的服務器變量ide
query_cache_min_res_unit:
查詢緩存中內存塊的最小分配單位,默認4k,較小值會減小浪費,但會致使更頻繁的內存分配操做,較大值會帶來浪費,會致使碎片過多,內存不足
query_cache_limit:
單個查詢結果能緩存的最大值,在MariaDB 10.2.x版本中默認爲10M,對於查詢結果過大而沒法緩存的語句,建議使用SQL_NO_CACHE
query_cache_size:
查詢緩存總共可用的內存空間;單位字節,必須是1024的整數倍,最小值40KB,低於此值有警報
query_cache_wlock_invalidate:
若是某表被其它的會話鎖定,是否仍然能夠從查詢緩存中返回結果,默認值爲OFF,表示能夠在表被其它會話鎖定的場景中繼續從緩存返回數據;ON則表示不容許
query_cache_type:
是否開啓緩存功能,取值爲ON, OFF, DEMAND
MariaDB [yinzhengjie]> SHOW VARIABLES LIKE 'query_cache%'; #查看Mariadb 10.2.x默認的緩存相關服務器變量。 +------------------------------+---------+ | Variable_name | Value | +------------------------------+---------+ | query_cache_limit | 1048576 | #默認是10M | query_cache_min_res_unit | 4096 | #默認是4K | query_cache_size | 1048576 | #默認是10M | query_cache_strip_comments | OFF | | query_cache_type | OFF | #很顯然,默認是沒有開啓緩存的 | query_cache_wlock_invalidate | OFF | #默認是關閉的 +------------------------------+---------+ rows in set (0.00 sec) MariaDB [yinzhengjie]> MariaDB [yinzhengjie]>
5>.SELECT語句的緩存控制
SQL_CACHE:
顯式指定存儲查詢結果於緩存之中
SQL_NO_CACHE:
顯式查詢結果不予緩存
6>.query_cache_type參數變量
query_cache_type的值爲OFF或0時,查詢緩存功能關閉 query_cache_type的值爲ON或1時,查詢緩存功能打開,SELECT的結果符合緩存條件即會緩存,不然,不予緩存,顯式指定SQL_NO_CACHE,不予緩存,此爲默 query_cache_type的值爲DEMAND或2時,查詢緩存功能按需進行,顯式指定SQL_CACHE的SELECT語句纔會緩存;其它均不予緩存 博主推薦閱讀: https://mariadb.com/kb/en/library/server-system-variables/#query_cache_type https://dev.mysql.com/doc/refman/5.7/en/query-cache-configuration.html
7>.查詢緩存相關的狀態變量
Qcache_free_blocks:
處於空閒狀態 Query Cache中內存 Block 數
Qcache_total_blocks:
Query Cache 中總Block ,當Qcache_free_blocks相對此值較大時,可能用內存碎片,執行FLUSH QUERY CACHE清理碎片
Qcache_free_memory:
處於空閒狀態的 Query Cache 內存總量
Qcache_hits:Query Cache:
命中次數
Qcache_inserts:
向 Query Cache 中插入新的 Query Cache 的次數,即沒有命中的次數
Qcache_lowmem_prunes:
記錄由於內存不足而被移除出查詢緩存的查詢數
Qcache_not_cached:
沒有被 Cache 的 SQL 數,包括沒法被 Cache 的 SQL 以及因爲 query_cache_type 設置的不會被 Cache 的 SQL語句
Qcache_queries_in_cache:
在 Query Cache 中的 SQL 數量
MariaDB [yinzhengjie]> SHOW GLOBAL STATUS LIKE 'Qcache%'; #查詢MariaDB 10.2.x 緩存相關的狀態變量 +-------------------------+---------+ | Variable_name | Value | +-------------------------+---------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 1031336 | | Qcache_hits | 0 | | Qcache_inserts | 0 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 0 | | Qcache_queries_in_cache | 0 | | Qcache_total_blocks | 1 | +-------------------------+---------+ 8 rows in set (0.00 sec) MariaDB [yinzhengjie]>
8>.查詢緩存中內存塊的最小分配單位query_cache_min_res_unit計算公式
(query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache
9>.查詢緩存命中率計算公式
Qcache_hits / ( Qcache_hits + Qcache_inserts ) * 100%
10>.查詢緩存內存使用率計算公式
(query_cache_size – qcache_free_memory) / query_cache_size * 100%
四.InnoDB存儲引擎緩存
1>.InnoDB存儲引擎的緩衝池
一般InnoDB存儲引擎緩衝池的命中不該該小於99%.
2>.查看相關狀態變量
Innodb_buffer_pool_reads:
表示從物理磁盤讀取頁的次數
Innodb_buffer_pool_read_ahead:
預讀的次數
Innodb_buffer_pool_read_ahead_evicted:
預讀頁,可是沒有讀取就從緩衝池中被替換的頁數量,通常用來判斷預讀的效率
Innodb_buffer_pool_read_requests:
從緩衝池中讀取頁次數
Innodb_data_read:
總共讀入的字節數
Innodb_data_reads:
發起讀取請求的次數,每次讀取可能須要讀取多個頁
MariaDB [yinzhengjie]> SHOW GLOBAL STATUS LIKE 'innodb%read%'; #查看MariaDB 10.2.x默認相關狀態變量 +--------------------------------------------------------+---------+ | Variable_name | Value | +--------------------------------------------------------+---------+ | Innodb_buffer_pool_read_ahead_rnd | 0 | | Innodb_buffer_pool_read_ahead | 0 | | Innodb_buffer_pool_read_ahead_evicted | 0 | | Innodb_buffer_pool_read_requests | 2951 | | Innodb_buffer_pool_reads | 369 | | Innodb_data_pending_reads | 0 | | Innodb_data_read | 6113792 | | Innodb_data_reads | 390 | | Innodb_pages_read | 368 | | Innodb_pages0_read | 11 | | Innodb_rows_read | 179 | | Innodb_system_rows_read | 0 | | Innodb_secondary_index_triggered_cluster_reads | 0 | | Innodb_secondary_index_triggered_cluster_reads_avoided | 0 | | Innodb_encryption_rotation_pages_read_from_cache | 0 | | Innodb_encryption_rotation_pages_read_from_disk | 0 | +--------------------------------------------------------+---------+ 16 rows in set (0.00 sec) MariaDB [yinzhengjie]>
3>.Innodb緩衝池命中率計算公式
(Innodb_buffer_pool_read_requests)/(Innodb_buffer_pool_read_requests + Innodb_buffer_pool_read_ahead + Innodb_buffer_pool_reads)
4>.平均每次讀取的字節數計算公式
Innodb_data_read/Innodb_data_reads