mysql緩存設置

MySQL 可調節設置可以應用於整個 mysqld 進程,也可以應用於單個客戶機會話。
服務器端的設置
每個表都可以表示爲磁盤上的一個文件,必須先打開,後讀取。爲了加快從文件中讀取數據的過程,mysqld 對這些打開文件進行了緩存,其最大數目由 /etc/mysqld.conf 中的 table_cache 指定。清單 4 給出了顯示與打開表有關的活動的方式。
清單 4. 顯示打開表的活動
mysql> SHOW STATUS LIKE 'open%tables'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Open_tables | 5000 | | Opened_tables | 195 | +---------------+-------+ 2 rows in set (0.00 sec)

清單 4 說明目前有 5,000 個表是打開的,有 195 個表需要打開,因爲現在緩存中已經沒有可用文件描述符了(由於統計信息在前面已經清除了,因此可能會存在 5,000 個打開表中只有 195 個打開記錄的情況)。如果 Opened_tables 隨着重新運行 SHOW STATUS 命令快速增加,就說明緩存命中率不夠。如果 Open_tables 比 table_cache 設置小很多,就說明該值太大了(不過有空間可以增長總不是什麼壞事)。例如,使用 table_cache = 5000 可以調整表的緩存。
與表的緩存類似,對於線程來說也有一個緩存。 mysqld 在接收連接時會根據需要生成線程。在一個連接變化很快的繁忙服務器上,對線程進行緩存便於以後使用可以加快最初的連接。
清單 5 顯示如何確定是否緩存了足夠的線程。
清單 5. 顯示線程使用統計信息
mysql> SHOW STATUS LIKE 'threads%'; +-------------------+--------+ | Variable_name | Value | +-------------------+--------+ | Threads_cached | 27 | | Threads_connected | 15 | | Threads_created | 838610 | | Threads_running | 3 | +-------------------+--------+ 4 rows in set (0.00 sec)

此處重要的值是 Threads_created,每次 mysqld 需要創建一個新線程時,這個值都會增加。如果這個數字在連續執行 SHOW STATUS 命令時快速增加,就應該嘗試增大線程緩存。例如,可以在 my.cnf 中使用 thread_cache = 40 來實現此目的。
關鍵字緩衝區保存了 MyISAM 表的索引塊。理想情況下,對於這些塊的請求應該來自於內存,而不是來自於磁盤。清單 6 顯示瞭如何確定有多少塊是從磁盤中讀取的,以及有多少塊是從內存中讀取的。
清單 6. 確定關鍵字效率
mysql> show status like '%key_read%'; +-------------------+-----------+ | Variable_name | Value | +-------------------+-----------+ | Key_read_requests | 163554268 | | Key_reads | 98247 | +-------------------+-----------+ 2 rows in set (0.00 sec)

Key_reads 代表命中磁盤的請求個數, Key_read_requests 是總數。命中磁盤的讀請求數除以讀請求總數就是不中比率 —— 在本例中每 1,000 個請求,大約有 0.6 個沒有命中內存。如果每 1,000 個請求中命中磁盤的數目超過 1 個,就應該考慮增大關鍵字緩衝區了。例如,key_buffer = 384M 會將緩衝區設置爲 384MB。
臨時表可以在更高級的查詢中使用,其中數據在進一步進行處理(例如 GROUP BY 字句)之前,都必須先保存到臨時表中;理想情況下,在內存中創建臨時表。但是如果臨時表變得太大,就需要寫入磁盤中。清單 7 給出了與臨時表創建有關的統計信息。
清單 7. 確定臨時表的使用
mysql> SHOW STATUS LIKE 'created_tmp%'; +-------------------------+-------+ | Variable_name | Value | +-------------------------+-------+ | Created_tmp_disk_tables | 30660 | | Created_tmp_files | 2 | | Created_tmp_tables | 32912 | +-------------------------+-------+ 3 rows in set (0.00 sec)

每次使用臨時表都會增大 Created_tmp_tables; 基於磁盤的表也會增大 Created_tmp_disk_tables。 對於這個比率,並沒有什麼嚴格的規則,因爲這依賴於所涉及的查詢。長時間觀察 Created_tmp_disk_tables 會顯示所創建的磁盤表的比率,您可以確定設置的效率。 tmp_table_size 和 max_heap_table_size 都可以控制臨時表的最大大小,因此請確保在 my.cnf 中對這兩個值都進行了設置。
每個會話 的設置
下面這些設置針對於每個會話。在設置這些數字時要十分謹慎,因爲它們在乘以可能存在的連接數時候,這些選項表示大量的內存!您可以通過代碼修改會話 中的這些數字,或者在 my.cnf 中爲所有會話修改這些設置。
當 MySQL 必須要進行排序時,就會在從磁盤上讀取數據時分配一個排序緩衝區來存放這些數據行。如果要排序的數據太大,那麼數據就必須保存到磁盤上的臨時文件中,並再 次進行排序。如果 sort_merge_passes 狀態變量很大,這就指示了磁盤的活動情況。清單 8 給出了一些與排序相關的狀態計數器信息。
清單 8. 顯示排序統計信息
mysql> SHOW STATUS LIKE "sort%"; +-------------------+---------+ | Variable_name | Value | +-------------------+---------+ | Sort_merge_passes | 1 | | Sort_range | 79192 | | Sort_rows | 2066532 | | Sort_scan | 44006 | +-------------------+---------+ 4 rows in set (0.00 sec)

如果 sort_merge_passes 很大,就表示需要注意 sort_buffer_size。例如, sort_buffer_size = 4M 將排序緩衝區設置爲 4MB。
MySQL 也會分配一些內存來讀取表。理想情況下,索引提供了足夠多的信息,可以只讀入所需要的行,但是有時候查詢(設計不佳或數據本性使然)需要讀取表中大量數 據。要理解這種行爲,需要知道運行了多少個 SELECT 語句,以及需要讀取表中的下一行數據的次數(而不是通過索引直接訪問)。實現這種功能的命令如清單 9 所示。
清單 9. 確定表掃描比率
mysql> SHOW STATUS LIKE "com_select"; +---------------+--------+ | Variable_name | Value | +---------------+--------+ | Com_select | 318243 | +---------------+--------+ 1 row in set (0.00 sec) mysql> SHOW STATUS LIKE "handler_read_rnd_next"; +-----------------------+-----------+ | Variable_name | Value | +-----------------------+-----------+ | Handler_read_rnd_next | 165959471 | +-----------------------+-----------+ 1 row in set (0.00 sec)

Handler_read_rnd_next / Com_select 得出了表掃描比率 —— 在本例中是 521:1。如果該值超過 4000,就應該查看 read_buffer_size,例如 read_buffer_size = 4M。如果這個數字超過了 8M,就應該與開發人員討論一下對這些查詢進行調優了!

查看數據庫緩存配置情況
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的配置文件my.ini或my.cnf中找到如下內容:
# Query cache is used to cache SELECT results and later return them
# without actual executing the same query once again. Having the query
# cache enabled may result in significant speed improvements, if your
# have a lot of identical queries and rarely changing tables. See the
# "Qcache_lowmem_prunes" status variable to check if the current value
# is high enough for your load.
# Note: In case your tables change very often or if your queries are
# textually different every time, the query cache may result in a
# slowdown instead of a performance improvement.
query_cache_size=0
以上信息是默認配置,其註釋意思是說,MYSQL的查詢緩存用於緩存select查詢結果,並在下次接收到同樣的查詢請求時,不再執行實際查詢處理而直接 返回結果,有這樣的查詢緩存能提高查詢的速度,使查詢性能得到優化,前提條件是你有大量的相同或相似的查詢,而很少改變表裏的數據,否則沒有必要使用此功 能。可以通過Qcache_lowmem_prunes變量的值來檢查是否當前的值滿足你目前系統的負載。注意:如果你查詢的表更新比較頻繁,而且很 少有相同的查詢,最好不要使用查詢緩存。
具體配置方法:
1. 將query_cache_size設置爲具體的大小,具體大小是多少取決於查詢的實際情 況,但最好設置爲1024的倍數,參考值32M。
2. 增加一行:query_cache_type=1
query_cache_type參數用於控制緩存的類型,注意這個值不能隨便設置,必須設置爲數字,可選項目以及說明如下:
如果設置爲0,那麼可以說,你的緩存根本就沒有用,相當於禁用了。但是這種情況下query_cache_size設置的大小系統是否要爲其分配呢,這個 問題有待於測試?
如果設置爲1,將會緩存所有的結果,除非你的select語句使用SQL_NO_CACHE禁用了查詢緩存。
如果設置爲2,則只緩存在select語句中通過SQL_CACHE指定需要緩存的查詢。
OK,配置完後的部分文件如下:
query_cache_size=128M
query_cache_type=1
保存文件,重新啓動MYSQL服務,然後通過如下查詢來驗證是否真正開啓了:
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 | 134217728 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
+——————————+———–+
6 rows in set (0.00 sec)
主要看query_cache_size和query_cache_type的值是否跟我們設的一致:
這裏query_cache_size的值是134217728,我們設置的是128M,實際是一樣的,只是單位不同,可以自己換算 下:134217728 = 128*1024*1024。
query_cache_type設置爲1,顯示爲ON,這個前面已經說過了。
總之,看到上邊的顯示錶示設置正確,但是在實際的查詢中是否能夠緩存查詢,還需要手動測試下,我們可以通過show status like '%Qcache%';語句來測試,現在我們開啓了查詢緩存功能,在執行查詢前,我們先看看相關參數的值:
mysql> show status like '%Qcache%';
+————————-+———–+
| Variable_name | Value |
+————————-+———–+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 134208800 |
| Qcache_hits | 0 |
MySQL query cache從4.1版本開始提供了,不過值今天本人才對其進行研究。默認配置下,MySQL的該功能是沒有啓動的,可能你通過show variables like '%query_cache%';會發現其變量have_query_cache的值是yes,MYSQL初學者很容易以爲這個參數爲YES就代表開啓了 查詢緩存,實際上是不對的,該參數表示當前版本的MYSQL是否支持Query Cache,實際上是否開啓查詢緩存是看另外一個參數的值:query_cache_size ,該值爲0,表示禁用query cache,而默認配置正是配置爲0。
配置方法:
在MYSQL的配置文件my.ini或my.cnf中找到如下內容:
# Query cache is used to cache SELECT results and later return them
# without actual executing the same query once again. Having the query
# cache enabled may result in significant speed improvements, if your
# have a lot of identical queries and rarely changing tables. See the
# "Qcache_lowmem_prunes" status variable to check if the current value
# is high enough for your load.
# Note: In case your tables change very often or if your queries are
# textually different every time, the query cache may result in a
# slowdown instead of a performance improvement.
query_cache_size=0
以上信息是默認配置,其註釋意思是說,MYSQL的查詢緩存用於緩存select查詢結果,並在下次接收到同樣的查詢請求時,不再執行實際查詢處理而直接 返回結果,有這樣的查詢緩存能提高查詢的速度,使查詢性能得到優化,前提條件是你有大量的相同或相似的查詢,而很少改變表裏的數據,否則沒有必要使用此功 能。可以通過Qcache_lowmem_prunes變量的值來檢查是否當前的值滿足你目前系統的負載。注意:如果你查詢的表更新比較頻繁,而且很少有 相同的查詢,最好不要使用查詢緩存。
具體配置方法:
1. 將query_cache_size設置爲具體的大小,具體大小是多少取決於查詢的實際情況,但最好設置爲1024的倍數,參考值32M。
2. 增加一行:query_cache_type=1
query_cache_type參數用於控制緩存的類型,注意這個值不能隨便設置,必須設置爲數字,可選項目以及說明如下:
如果設置爲0,那麼可以說,你的緩存根本就沒有用,相當於禁用了。但是這種情況下query_cache_size設置的大小系統是否要爲其分配呢,這個 問題有待於測試?
如果設置爲1,將會緩存所有的結果,除非你的select語句使用SQL_NO_CACHE禁用了查詢緩存。
如果設置爲2,則只緩存在select語句中通過SQL_CACHE指定需要緩存的查詢。
OK,配置完後的部分文件如下:
query_cache_size=128M
query_cache_type=1
保存文件,重新啓動MYSQL服務,然後通過如下查詢來驗證是否真正開啓了:
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 | 134217728 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
+——————————+———–+
6 rows in set (0.00 sec)
主要看query_cache_size和query_cache_type的值是否跟我們設的一致:
這裏query_cache_size的值是134217728,我們設置的是128M,實際是一樣的,只是單位不同,可以自己換算 下:134217728 = 128*1024*1024。
query_cache_type設置爲1,顯示爲ON,這個前面已經說過了。
總之,看到上邊的顯示錶示設置正確,但是在實際的查詢中是否能夠緩存查詢,還需要手動測試下,我們可以通過show status like '%Qcache%';語句來測試,現在我們開啓了查詢緩存功能,在執行查詢前,我們先看看相關參數的值:
mysql> show status like '%Qcache%';
+————————-+———–+
| Variable_name | Value |
+————————-+———–+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 134208800 |

| Qcache_hits | 0 |



 一、什麼時候應用系統會從緩存中獲取數據?
  數據庫從服務器上讀取數據時,可以從硬盤的數據文件中獲取數據,也可以從數據庫緩存中讀取數據。現在數據庫管理員需要搞清楚的是,在什麼樣的情況下,系統是從緩存中讀取數據,而不是從硬盤的數據文件中讀取數據?
  簡單的說,數據緩存就是內存中的一塊存儲區域,其存儲了用戶的SQL文本以及相關的查詢結果。通常情況下,用戶下次查詢時,如果所使用的SQL文本是相同的,並且自從上次查詢後,相關的紀錄沒有被更新過,此時數據庫就直接採用緩存中的內容。從這個原則中,可以看到如果要直接使用緩存中的數據,至少要滿足以下幾個條件。
  一是所採用的SQL文本是相同的。當前後兩次用戶使用了相同的SQL語句(假設不考慮其他條件),則服務器會從緩存中讀取結果,而不需要再去解析和執行SQL語句。這裏需要注意的是,這裏的SQL文本必須一次不差的完全相同。如果前後兩次查詢,使用了不同的查詢條件。如第一次查詢時沒有輸入Where條件語句。後來發現數據量過多,利用了Where條件了過濾查詢的結果。此時即使最後的查詢結果是相同的,系統仍然是從數據文件中獲取數據,而不是從數據緩存中。再如,Select後面所使用的字段名稱也必須是相同的。如果有一個字段名稱不同或者前後兩次查詢所使用的字段數量不同,則系統都會認爲是不同的SQL語句,而重新解析並查詢。
  二是從數據緩存的角度考慮,大小寫是不敏感的。如前後兩次查詢時,採用的字段名稱可能只有大小寫的差異。如第一次使用的是大小,第二次使用的是小寫,這系統認爲仍然是相同的SQL語句。或者說關鍵字大小寫等等這都是不敏感的。
  三是要滿足二次查詢之間,數據記錄包括表結構都沒有被更改過。如果記錄所在的標更改了,如增加了一個字段等等,此時使用這個表的所有緩衝數據系統將自動清空。這裏需要注意,這裏指的更改是一個廣義的更改,包括表中任何數據或者結果的改變。舉一個簡單的例子,第一次查詢時用戶需要查詢2010年的出貨數據。查詢後有用戶在這個表中插入了一條2011年1月份的出貨信息。然後又有用戶需要查詢2010年的出貨信息。使用的SQL語句與第一次查詢時完全相同。在這種情況下,數據庫系統會使用緩存中的數據嗎?答案是否定的。因爲當中間用戶插入一條記錄時,系統會自動清空跟這個表相關的所有緩存記錄。當第二次查詢時,緩存中已經沒有這張表對應的緩存信息。此時就需要重新解析並查詢。
  四是需要注意,默認字符集對緩存命中率的影響。通常情況下,如果客戶端與服務器之間所採用的默認字符集不同,則即使查詢語句相同、在兩次查詢之間記錄與表結構也沒有被更改,系統仍然認爲是不同的查詢。對於這一點需要特別的注意,大家比較容易忽視。
  二、提高緩存命中率的建議。
  從上面的條件分析中可以看出,利用緩存中的數據具有比較嚴格的條件。其實這些條件也是合情合理的。主要是爲了保障數據的一致性。對以上這些條件有深入的認識之後,現在數據庫管理員需要考慮的是,如何來提高這個緩存的命中率?對此筆者有如下幾個建議。
  一是在配置時,客戶端與服務器端要使用相同的字符集。如果客戶端(或者說第三方工具)與服務器端使用的字符集不同,那麼任何情況下都不會使用緩存功能。特別在國內,需要用到中文的字符集。此時特別需要注意,客戶端默認字符集要與服務器端的默認字符集相同。注意,這裏是相同,而不是兼容。有時候即使採用了不同的字符集,客戶端上仍然可以正常顯示。這主要是因爲有些字符集雖然不相同,但是是相互兼容的。在緩存管理上,需要相同,光兼容還不行。
  二是在客戶端上,要固化查詢的語句。如現在有財務人員和採購人員同時從系統中查詢11月份的出貨數據。顯然他們崗位職責不同,所需要字段的內容是不同的。此時在客戶端出,可以允許用戶設置自己所需要的表單格式。但是筆者建議,後臺所採用的SQL語句最好是相同的。這裏數據會經過三個渠道:後臺數據庫、客戶端、用戶。筆者的意識時,後臺數據庫與客戶端之間的交互採用相同的SQL語句。然後客戶端與用戶之間進行交互時,根據用戶定義的格式(包括字段前後的排列、不包括查詢條件語句的差異)向用戶顯示數據。此時由於採用了相同的SQL語句(只是用戶對於顯示格式的要求不同),從而可以提高應用系統的查詢效率。
  三是提高內存中緩存的配置,來提高命中率。一般在服務器啓動時,操作系統會跟數據庫軟件協商緩存空間的大小。當緩存工作不足時,緩存中最舊的緩存記錄會被最新的消息所覆蓋。可見,如果能夠提高緩存空間,就可以提高命中率。這就好像打靶,目標多了,命中的機率也會高許多。不過用戶的併發數越多,這個設置的效果會越不明顯。
  四是通過分區表可以提高緩存的命中率。在上面的條件分析中,大家可以看到,只要所查詢的表中插入了一條記錄,系統就會清空緩存記錄。現在以查詢出貨記錄爲例。出貨記錄表每天都在更新,而用戶在年初時,會經常需要查詢上一年的出貨記錄。此時由於這個表中的數據每個小時都在更新,那麼緩存中的信息會不斷的被情況。此時緩存的命中率顯然不會很高。針對這種情況,筆者建議可以採用分區表。如可以通過系統設置,將2010年的出貨記錄單獨存放在一個出貨的分區表中。即每一個年度都使用一張單獨的分區表。此時2011年的紀錄,就不會影響到2010年的分區表。此時如果用戶重複查詢2010年的出貨信息,只要其使用的SQL語句相同(沒有采用不同的查詢條件),那麼就可以享受緩存機制所帶來的效益,提高應用系統的查詢效果。。
  三、多個應用對緩存的影響。
  通常情況下,MySQL數據庫的緩存是根據服務器內存的大小自動分配的。如果一臺服務器上只有一個MySQL應用,那麼固然最好。不過在實際工作中,爲了降低信息化投資的成本,往往會在同一臺服務器上佈置多個信息化應用。由於其他信息化應用也需要使用內存的空間作爲緩存,那麼MySQL數據庫中緩存空間就可能變小。如果遇到這種情況下,數據庫管理員需要跟系統工程師進行協商,爲各種不同的應用根據性能要求的不同,手工設置不同的緩存空間。如此的話,就可以避免同一臺服務器上不同信息化應用對緩存的衝突。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章