MySQL的查詢快取機制基本學習教程_Mysql

來源:互聯網
上載者:User

MySQL緩衝機制簡單的說就是緩衝sql文本及查詢結果,如果運行相同的sql,伺服器直接從緩衝中取到結果,而不需要再去解析和執行sql。如果表更改 了,那麼使用這個表的所有緩衝查詢將不再有效,查詢快取值的相關條目被清空。更改指的是表中任何資料或是結構的改變,包括INSERT、UPDATE、 DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE等,也包括那些映射到改變了的表的使用MERGE表的查詢。顯然,這對於頻繁更新的表,查詢快取是不適合的,而對於一些不常改變資料且有 大量相同sql查詢的表,查詢快取會節約很大的效能。

命中條件

緩衝存在一個hash表中,通過查詢SQL,查詢資料庫,用戶端協議等作為key.在判斷是否命中前,MySQL不會解析SQL,而是直接使用SQL去查詢快取,SQL任何字元上的不同,如空格,注釋,都會導致緩衝不命中.

如果查詢中有不確定資料,例如CURRENT_DATE()和NOW()函數,那麼查詢完畢後則不會被緩衝.所以,包含不確定資料的查詢是肯定不會找到可用緩衝的

 

工作流程

1. 伺服器接收SQL,以SQL和一些其他條件為key尋找緩衝表(額外效能消耗)

2. 如果找到了緩衝,則直接返回緩衝(效能提升)

3. 如果沒有找到緩衝,則執行SQL查詢,包括原來的SQL解析,最佳化等.

4. 執行完SQL查詢結果以後,將SQL查詢結果存入緩衝表(額外效能消耗)


緩衝失效

當某個表正在寫入資料,則這個表的緩衝(命中檢查,緩衝寫入等)將會處於失效狀態.在Innodb中,如果某個事務修改了表,則這個表的緩衝在事務提交前都會處於失效狀態,在這個事務提交前,這個表的相關查詢都無法被緩衝.

 

緩衝的記憶體管理

緩衝會在記憶體中開闢一塊記憶體(query_cache_size)來維護快取資料,其中有大概40K的空間是用來維護緩衝的中繼資料的,例如空間記憶體,資料表和查詢結果的映射,SQL和查詢結果的映射等.

MySQL將這個大記憶體塊分為小的記憶體塊(query_cache_min_res_unit),每個小塊中儲存自身的類型,大小和查詢結果資料,還有指向前後記憶體塊的指標.

MySQL需要設定單個小儲存塊的大小,在SQL查詢開始(還未得到結果)時就去申請一塊空間,所以即使你的快取資料沒有達到這個大小,也需要用這個大小的資料區塊去存(這點跟Linux檔案系統的Block一樣).如果結果超出這個記憶體塊的大小,則需要再去申請一個記憶體塊.當查詢完成發現申請的記憶體塊有富餘,則會將富餘的空間釋放掉,這就會造成記憶體片段問題,見下圖

此處查詢1和查詢2之間的空白部分就是記憶體片段,這部分空閑記憶體是有查詢1查詢完以後釋放的,假設這個空間大小小於MySQL設定的記憶體塊大小,則無法再被使用,造成片段問題

在查詢開始時申請分配記憶體Block需要鎖住整個空閑記憶體區,所以分配記憶體塊是非常消耗資源的.注意這裡所說的分配記憶體是在MySQL初始化時就開闢的那塊記憶體上分配的.

 

緩衝的使用時機

衡量開啟緩衝是否對系統有效能提升是一個很難的話題

1. 通過快取命中率判斷, 快取命中率 = 快取命中次數 (Qcache_hits) / 查詢次數 (Com_select)

2. 通過緩衝寫入率, 寫入率 = 緩衝寫入次數 (Qcache_inserts) / 查詢次數 (Qcache_inserts)

3. 通過 命中-寫入率 判斷, 比率 = 叫用次數 (Qcache_hits) / 寫入次數 (Qcache_inserts), 高效能MySQL中稱之為比較能反映效能提升的指數,一般來說達到3:1則算是查詢快取有效,而最好能夠達到10:1

 

緩衝配置參數

1. query_cache_type: 是否開啟緩衝

可選項

1) OFF: 關閉

2) ON: 總是開啟

3) DEMAND: 只有明確寫了SQL_CACHE的查詢才會吸入緩衝

 

2. query_cache_size: 緩衝使用的總記憶體空間大小,單位是位元組,這個值必須是1024的整數倍,否則MySQL實際分配可能跟這個數值不同(感覺這個應該跟檔案系統的blcok大小有關)

 

3. query_cache_min_res_unit: 分配記憶體塊時的最小單位大小

 

4. query_cache_limit: MySQL能夠緩衝的最大結果,如果超出,則增加 Qcache_not_cached的值,並刪除查詢結果

 

5. query_cache_wlock_invalidate: 如果某個資料表被鎖住,是否仍然從緩衝中返回資料,預設是OFF,表示仍然可以返回

 

GLOBAL STAUS 中 關於 緩衝的參數解釋:

Qcache_free_blocks: 緩衝池中空閑塊的個數

Qcache_free_memory: 緩衝中空閑記憶體量

Qcache_hits: 快取命中次數

Qcache_inserts: 緩衝寫入次數

Qcache_lowmen_prunes: 因記憶體不足刪除緩衝次數

Qcache_not_cached: 查詢未被緩衝次數,例如查詢結果超出緩衝塊大小,查詢中包含可變函數等

Qcache_queries_in_cache: 當前緩衝中緩衝的SQL數量

Qcache_total_blocks: 緩衝總block數

 

減少片段策略

1. 選擇合適的block大小

2. 使用 FLUSH QUERY CACHE 命令整理片段.這個命令在整理緩衝期間,會導致其他串連無法使用查詢快取

PS: 清空緩衝的命令式 RESET QUERY CACHE

 

查詢快取問題分析

InnoDB與查詢快取

Innodb會對每個表設定一個事務計數器,裡面儲存當前最大的事務ID.當一個事務提交時,InnoDB會使用MVCC中系統事務ID最大的事務ID跟新當前表的計數器.

只有比這個最大ID大的事務能使用查詢快取,其他比這個ID小的事務則不能使用查詢快取.

另外,在InnoDB中,所有有加鎖操作的事務都不使用任何查詢快取

查詢必須是完全相同的(逐位元組相同)才能夠被認為是相同的。另外,同樣的查詢字串由於其它原因可能認為是不同的。使用不同的資料庫、不同的協議版本或者不同 預設字元集的查詢被認為是不同的查詢並且分別進行緩衝。

下面sql查詢快取認為是不同的:

SELECT * FROM tbl_name Select * from tbl_name

 

查詢快取相關參數

mysql> SHOW VARIABLES LIKE '%query_cache%'; 
+------------------------------+---------+ | Variable_name        | Value  | +------------------------------+---------+ | have_query_cache       | YES   | --查詢快取是否可用 | query_cache_limit      | 1048576 | --可緩衝具體查詢結果的最大值 | query_cache_min_res_unit   | 4096  |  | query_cache_size       | 599040 | --查詢快取的大小 | query_cache_type       | ON   | --阻止或是支援查詢快取 | query_cache_wlock_invalidate | OFF   |  +------------------------------+---------+ 

下面是一個簡單的MySQL查詢快取機制例子:

[mysql@csdba1850 ~]$ mysql -u root -p 
Enter password:  Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.0.45-community MySQL Community Edition (GPL)  Type 'help;' or '\h' for help. Type '\c' to clear the buffer. 

 

mysql> set global query_cache_size = 600000; --設定緩衝記憶體 
Query OK, 0 rows affected (0.00 sec) 

 

mysql> set session query_cache_type = ON; --開啟查詢快取 
Query OK, 0 rows affected (0.00 sec) 
 mysql> use test 
Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A  Database changed 
mysql> show tables; 
+----------------+ | Tables_in_test | +----------------+ | animals    |  | person     |  +----------------+ 5 rows in set (0.00 sec)  mysql> select count(*) from animals; +----------+ | count(*) | +----------+ |    6 |  +----------+ 1 row in set (0.00 sec)  --Qcache_hits表示sql查詢在緩衝中命中的累計次數,是累加值。 
mysql> SHOW STATUS LIKE 'Qcache_hits'; 
+---------------+-------+ | Variable_name | Value | +---------------+-------+ | Qcache_hits  | 0   | --0次 +---------------+-------+ 8 rows in set (0.00 sec)  mysql> select count(*) from animals; +----------+ | count(*) | +----------+ |    6 |  +----------+ 1 row in set (0.00 sec) 

 

mysql> SHOW STATUS LIKE 'Qcache%'; 

 

+---------------+-------+ | Variable_name | Value | +---------------+-------+ | Qcache_hits  | 1   | --表示sql在緩衝中直接得到結果,不需要再去解析 +---------------+-------+ 8 rows in set (0.00 sec) 

 

mysql> select count(*) from animals; 
+----------+ | count(*) | +----------+ |    6 |  +----------+ 1 row in set (0.00 sec) 

 

mysql> select count(*) from animals; 
+----------+ | count(*) | +----------+ |    6 |  +----------+ 1 row in set (0.00 sec) 

 

mysql> SHOW STATUS LIKE 'Qcache_hits'; 
+---------------+-------+ | Variable_name | Value | +---------------+-------+ | Qcache_hits  | 3   |  --上面的sql也是是從緩衝中直接取到結果 +---------------+-------+ 1 row in set (0.00 sec) 
 mysql> insert into animals select 9,'testsds' ; --插入資料後,跟這個表所有相關的sql緩衝就會被清空掉 
Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0 
 mysql> select count(*) from animals; 
+----------+ | count(*) | +----------+ |    7 |  +----------+ 1 row in set (0.00 sec) 
 mysql> SHOW STATUS LIKE 'Qcache_hits'; 
+---------------+-------+ | Variable_name | Value | +---------------+-------+ | Qcache_hits  | 3  | --還是等於3,說明上一條sql是沒有直接從緩衝中直接得到的 +---------------+-------+ 1 row in set (0.00 sec) 

 

mysql> select count(*) from animals; 
+----------+ | count(*) | +----------+ |    7 |  +----------+ 1 row in set (0.00 sec) 

 

mysql> SHOW STATUS LIKE 'Qcache_hits';  
+---------------+-------+ | Variable_name | Value | +---------------+-------+ | Qcache_hits  | 4   |  +---------------+-------+ 1 row in set (0.00 sec) 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.