MySQL/MariaDB數據庫的查詢緩存優化

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

 
MariaDB [yinzhengjie]> SHOW VARIABLES LIKE 'query_cache%';    #查看默認的緩存相關服務器變量(優化查詢緩存流程圖以下)

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]> 
MariaDB [yinzhengjie]> SHOW GLOBAL STATUS LIKE 'Qcache%';       #查詢MariaDB 10.2.x 緩存相關的狀態變量

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]> 
MariaDB [yinzhengjie]> SHOW GLOBAL STATUS LIKE 'innodb%read%';     #查看MariaDB 10.2.x默認相關狀態變量

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
相關文章
相關標籤/搜索