[轉]MySql查詢緩存機制


本文轉自:http://flatfish2000.iteye.com/blog/506525

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

  查詢必須是完全相同的(逐字節相同)才能夠被認為是相同的。另外,同樣的查詢字符串由於其它原因可能認為是不同的。使用不同的數據庫、不同的協議版本或者不同 默認字符集的查詢被認為是不同的查詢並且分別進行緩存。

  下面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@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) 

 

 

MySQL 查詢緩存

從 MySQL 4.0.1 開始,MySQL server 有一個重要的特征:Query Cache。 當在使用中,查詢緩存會存儲一個 SELECT 查詢的文本與被傳送到客戶端的相應結果。如果之后接收到一個同樣的查詢,服務器將從查詢緩存中檢索結果,而不是再次分析和執行這個同樣的查詢。

注意:查詢緩存絕不返回過期數據。當數據被修改后,在查詢緩存中的任何相關詞條均被轉儲清除。

在某些表並不經常更改,而你又對它執行大量的相同查詢時,查詢緩存將是非常有用的。對於許多 WEB 服務器使用大量的動態信息,這是一個很典型的情況。

下面是查詢緩存的一個性能數據。(這些結果的產生,是通過在一個 a Linux Alpha 2 x 500 MHz、2GB RAM 和 64MB 查詢緩存上執行 MySQL 基准套件和到的):

如果你執行的所有查詢均是簡單的(比如從表中一行一行的選取);但是仍然是不同的,所以該查詢不能被緩沖,查詢緩存處於活動時,開銷為 13%。這可以被看作是最差的情況。然而,在實際情況下,查詢是比我們的簡單示例要復雜得多的,所以開銷通常顯著得低。
在只有一行記錄表中搜索一行后,搜索將快 238% 。這可以被認為是接近於對一個被緩沖的查詢所期望的最小的加速。
如果你希望禁用查詢緩存,設置 query_cache_size=0。禁用了查詢緩存,將沒有明顯的開銷。(在配置選項 --without-query-cache 的幫助下,查詢緩存可以被排除在外碼之外)
6.9.1 查詢緩存如何運作
查詢在分析之前先被比較,因而

SELECT * FROM tbl_name



Select * from tbl_name

對於查詢緩存被當作是不同的查詢,因而查詢需要嚴格的一致(字節對字節的),才會被認為是同樣的。 另外,如果一個客戶端使用一個新的連接協議格式或不同於其它客戶端的另一個字符集,一個查詢將被視為不同的。

使用不同數據庫的,使用不同協議版本的,或使用不同的缺省字符串的查詢將被認為是不同的查詢,並將分別的緩沖。

高速緩沖不對 SELECT CALC_ROWS ... 和 SELECT FOUND_ROWS() ... 類型的查詢起作用,因為找到的行的數目也是被存儲在緩沖里的。

如果查詢結果被從查詢緩存中返回,那么狀態變量 Com_select 將不會被增加,但是 Qcache_hits 卻會增加。查看章節 6.9.4 查詢緩存的狀態和維護。

如果一個表發生的改變 (INSERT, UPDATE, DELETE, TRUNCATE, ALTER 或 DROP TABLE|DATABASE),那么所有這張表使用的緩沖的查詢(可能通過一個 MRG_MyISAM 表!)將被得失效,並從緩沖中移除。

InnoDB 表的事務所做的更改將在一個 COMMIT 被完成時,使數據失效。

如果一個查詢包括下面的函數,它將不能被緩沖: 函數  函數  函數 
User-Defined Functions  CONNECTION_ID  FOUND_ROWS 
GET_LOCK  RELEASE_LOCK  LOAD_FILE 
MASTER_POS_WAIT  NOW  SYSDATE 
CURRENT_TIMESTAMP  CURDATE  CURRENT_DATE 
CURTIME  CURRENT_TIME  DATABASE 
ENCRYPT (只有一個參數調用)  LAST_INSERT_ID  RAND 
UNIX_TIMESTAMP (無參數調用)  USER  BENCHMARK 



如果一個查詢包含用戶變量,引用 MySQL 系統數據庫,或下列之一的格式,SELECT ... IN SHARE MODE, SELECT ... INTO OUTFILE ..., SELECT ... INTO DUMPFILE ... 或 SELECT * FROM AUTOINCREMENT_FIELD IS NULL (檢索最后一個插入 ID - ODBC 語句),該查詢亦不可以被緩存。

然而,FOUND ROWS() 將返回正確的值,即使先前的查詢是從緩存中讀取的。

萬一一個查詢不使用任何表,或使用臨時表,或用戶對任何相關表有一個列權限,那么查詢將不會被緩存。

在一個查詢從查詢緩存中讀取前,MySQL 將檢查用戶對所有相關的數據庫和表有 SELECT 權限。如果不是這種情況,緩存的結果將不能被使用。

6.9.2 查詢緩存設置
查詢緩存為了 mysqld 添加了幾個 MySQL 系統變量,它可以在配置文件中被設置,或在啟動 mysqld 時的命令行上設置。

query_cache_limit 不緩存大於這個值的結果。(缺省為 1M)

query_cache_min_res_unit 這個變量從 4.1 被引進。 查詢的結果 (已被傳送到客戶端的數據) 在結果檢索期間被存儲到查詢緩存中。因而,數據不會以一個大塊地處理。查詢緩存在需要時分配塊用於處理這個數據,所以當一個塊被填充后,一個新的塊被分配。甚為內存分配操作是昂貴的,查詢緩存以最小的尺寸 query_cache_min_res_unit 分配塊。當一個查詢執行完成,最后的結果塊被修整到實際數據的尺寸大小,以便未使用的內存被釋放。
query_cache_min_res_unit 的缺省值為 4 KB,在大多數據情況下已夠用了。
如果你有許多查詢返回一個較小的結果,缺省的塊尺寸可能會引起內存碎片 (顯示為一個很大數量的空閑塊(Qcache_free_blocks),這將引起查詢緩存不得不因缺乏內存(Qcache_lowmem_prunes)而從緩存中刪除查詢)。在這種情況下,你應該減少 query_cache_min_res_unit。
如果你的主要查詢返回的是大的結果集(查看 Qcache_total_blocks 和 Qcache_queries_in_cache),你可以通過增加 query_cache_min_res_unit 來增加性能。然而,要小心不要將它設得太大。

query_cache_size 為了存儲老的查詢結果而分配的內存數量 (以字節指定) 。如果設置它為 0 ,查詢緩沖將被禁止(缺省值為 0 )。
query_cache_type 這個可以被設置為 (只能是數字) 選項  含義 
0  (OFF, 不緩存或重新得到結果) 
1  (ON, 緩存所有的結果,除了 SELECT SQL_NO_CACHE ... 查詢) 
2  (DEMAND, 僅緩存 SELECT SQL_CACHE ... 查詢) 

在一個線程(連接)內,查詢緩存的行為可以被改變。句法如下所示:

QUERY_CACHE_TYPE = OFF | ON | DEMAND QUERY_CACHE_TYPE = 0 | 1 | 2

選項  含義 
0 or OFF  不緩存或重新得到結果 
1 or ON  緩存所有的結果,除了 SELECT SQL_NO_CACHE ... 查詢 
2 or DEMAND  僅緩存 SELECT SQL_CACHE ... 查詢 

6.9.3 在 SELECT 中的查詢緩存選項
有兩個可能的查詢緩存相關的參數可以在一個 SELECT 查詢中被指定:


選項  含義 
SQL_CACHE  如果 QUERY_CACHE_TYPE 為 DEMAND,允許該查詢被緩存。如果 QUERY_CACHE_TYPE 為 ON,這是缺省的。如果 QUERY_CACHE_TYPE 為 OFF,它不做任何事 
SQL_NO_CACHE  使這個查詢不被緩存,不允許這個查詢被存儲到高速緩存中 

6.9.4 查詢緩存的狀態和維護
使用 FLUSH QUERY CACHE 命令,你可以整理查詢緩存,以更好的利用它的內存。這個命令不會從緩存中移除任何查詢。FLUSH TABLES 會轉儲清除查詢緩存。

RESET QUERY CACHE 使命從查詢緩存中移除所有的查詢結果。

你可以檢查查詢緩存在你的 MySQL 是否被引進:

mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+
1 row in set (0.00 sec)

在 SHOW STATUS 中,你可以監視查詢緩存的性能:

變量  含義 
Qcache_queries_in_cache  在緩存中已注冊的查詢數目 
Qcache_inserts  被加入到緩存中的查詢數目 
Qcache_hits  緩存采樣數數目 
Qcache_lowmem_prunes  因為缺少內存而被從緩存中刪除的查詢數目 
Qcache_not_cached  沒有被緩存的查詢數目 (不能被緩存的,或由於 QUERY_CACHE_TYPE) 
Qcache_free_memory  查詢緩存的空閑內存總數 
Qcache_free_blocks  查詢緩存中的空閑內存塊的數目 
Qcache_total_blocks  查詢緩存中的塊的總數目 

Total number of queries = Qcache_inserts + Qcache_hits + Qcache_not_cached.

查詢緩存使用變長的塊,因而 Qcache_total_blocks 和 Qcache_free_blocks 可能顯示查詢緩存的碎片。在 FLUSH QUERY CACHE 之后,只有剩余一個單獨的(大的)空閑塊。

注意:每個查詢最小需要兩個塊(一個用於存儲查詢文本,另一個或多個用於存儲查詢結果)。同樣的,每個被一個查詢使用的表需要一個塊,但是,如果有兩個或更多的查詢使用同一張表,僅僅只需要分配一個塊就行了。

你可以使用狀態變量 Qcache_lowmem_prunes 來諧調查詢緩存尺寸。它計數被從緩存中移除的查詢,該查詢的移除是為了釋放內存,以緩存新建的查詢。查詢緩存使用一個 least recently used (LRU) 策略來判斷從緩存中移除哪個查詢。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM