MYSQL性能查看(命中率,慢查詢)

網上有很多的文章教怎麼配置MySQL服務器,但考慮到服務器硬件配置的不同,具體應用的差別,那些文章的做法只能作爲初步設置參考,我們需要根據自己的情況進行配置優化,好的做法是MySQL服務器穩定運行了一段時間後運行,根據服務器的”狀態”進行優化。 
  mysql> show global status; 
  可以列出MySQL服務器運行各種狀態值,另外,查詢MySQL服務器配置信息語句: 
  mysql> show variables; 
  一、慢查詢 
  mysql> show variables like '%slow%'; 
  +------------------+-------+ 
  | Variable_name | Value | 
  +------------------+-------+ 
  | log_slow_queries | ON | 
  | slow_launch_time | 2 | 
  +------------------+-------+ 
  mysql> show global status like '%slow%'; 
  +---------------------+-------+ 
  | Variable_name | Value | 
  +---------------------+-------+ 
  | Slow_launch_threads | 0 | 
  | Slow_queries | 4148 | 
  +---------------------+-------+   


        配置中打開了記錄慢查詢,執行時間超過2秒的即爲慢查詢,系統顯示有4148個慢查詢,你可以分析慢查詢日誌,找出有問題的SQL語句,慢查詢時間不宜設 置過長,否則意義不大,最好在5秒以內,如果你需要微秒級別的慢查詢,可以考慮給MySQL打補丁:http://www.percona.com /docs/wiki/release:start,記得找對應的版本。 
  打開慢查詢日誌可能會對系統性能有一點點影響,如果你的MySQL是主-從結構,可以考慮打開其中一臺從服務器的慢查詢日誌,這樣既可以監控慢查詢,對系統性能影響又小。 




  二、連接數 
  經常會遇見”MySQL: ERROR 1040: Too many connections”的情況,一種是訪問量確實很高,MySQL服務器抗不住,這個時候就要考慮增加從服務器分散讀壓力,另外一種情況是MySQL配 置文件中max_connections值過小: 
  mysql> show variables like 'max_connections'; 
  +-----------------+-------+ 
  | Variable_name | Value | 
  +-----------------+-------+ 
  | max_connections | 256 | 
  +-----------------+-------+   


       這臺MySQL服務器最大連接數是256,然後查詢一下服務器響應的最大連接數: 
  mysql> show global status like ‘Max_used_connections’; 
  MySQL服務器過去的最大連接數是245,沒有達到服務器連接數上限256,應該沒有出現1040錯誤,比較理想的設置是: 
  Max_used_connections / max_connections * 100% ≈ 85% 
  最大連接數占上限連接數的85%左右,如果發現比例在10%以下,MySQL服務器連接數上限設置的過高了。 




  三、Key_buffer_size 
  key_buffer_size是對MyISAM表性能影響最大的一個參數,下面一臺以MyISAM爲主要存儲引擎服務器的配置: 
  mysql> show variables like ‘key_buffer_size’; 
  +-----------------+------------+ 
  | Variable_name | Value | 
  +-----------------+------------+ 
  | key_buffer_size | 536870912 | 
  +-----------------+------------+   


       分配了512MB內存給key_buffer_size,我們再看一下key_buffer_size的使用情況: 
  mysql> show global status like 'key_read%'; 
  +------------------------+-------------+ 
  | Variable_name | Value | mysql 
  +------------------------+-------------+ 
  | Key_read_requests | 27813678764 | 
  | Key_reads | 6798830 | 
  +------------------------+-------------+   


       一共有27813678764個索引讀取請求,有6798830個請求在內存中沒有找到直接從硬盤讀取索引,計算索引未命中緩存的概率: 
  key_cache_miss_rate = Key_reads / Key_read_requests * 100% 
  比如上面的數據,key_cache_miss_rate爲0.0244%,4000個索引讀取請求才有一個直接讀硬盤,已經很BT 了,key_cache_miss_rate在0.1%以下都很好(每1000個請求有一個直接讀硬盤),如果key_cache_miss_rate在 0.01%以下的話,key_buffer_size分配的過多,可以適當減少。 
  MySQL服務器還提供了key_blocks_*參數: 
  mysql> show global status like 'key_blocks_u%'; 
  +------------------------+-------------+ 
  | Variable_name | Value | 
  +------------------------+-------------+ 
  | Key_blocks_unused | 0 | 
  | Key_blocks_used | 413543 | 
  +------------------------+-------------+   


       Key_blocks_unused表示未使用的緩存簇(blocks)數,Key_blocks_used表示曾經用到的最大的blocks數,比如 這臺服務器,所有的緩存都用到了,要麼增加key_buffer_size,要麼就是過渡索引了,把緩存佔滿了。比較理想的設置: 
  Key_blocks_used / (Key_blocks_unused + Key_blocks_used) * 100% ≈ 80% 




  四、臨時表 
  mysql> show global status like 'created_tmp%'; 
  +-------------------------+---------+ 
  | Variable_name | Value | 
  +-------------------------+---------+ 
  | Created_tmp_disk_tables | 21197 | 
  | Created_tmp_files | 58 | 
  | Created_tmp_tables | 1771587 | 
  +-------------------------+---------+   


       每次創建臨時表,Created_tmp_tables增加,如果是在磁盤上創建臨時表,Created_tmp_disk_tables也增加,Created_tmp_files表示MySQL服務創建的臨時文件文件數,比較理想的配置是: 
  Created_tmp_disk_tables / Created_tmp_tables * 100% <= 25% 
  比如上面的服務器Created_tmp_disk_tables / Created_tmp_tables * 100% = 1.20%,應該相當好了。我們再看一下MySQL服務器對臨時表的配置: 
  mysql> show variables where Variable_name in ('tmp_table_size', 'max_heap_table_size'); 
  +---------------------+-----------+ 
  | Variable_name | Value | 
  +---------------------+-----------+ 
  | max_heap_table_size | 268435456 | 
  | tmp_table_size | 536870912 | 
  +---------------------+-----------+   


      只有256MB以下的臨時表才能全部放內存,超過的就會用到硬盤臨時表。 
  五、Open Table情況 
  mysql> show global status like 'open%tables%'; 
  +---------------+-------+ 
  | Variable_name | Value | 
  +---------------+-------+ 
  | Open_tables | 919 | 
  | Opened_tables | 1951 | 
  +---------------+-------+   


      Open_tables表示打開表的數量,Opened_tables表示打開過的表數量,如果Opened_tables數量過大,說明配置中 table_cache(5.1.3之後這個值叫做table_open_cache)值可能太小,我們查詢一下服務器table_cache值: 
  mysql> show variables like 'table_cache'; 
  +---------------+-------+ 
  | Variable_name | Value | 
  +---------------+-------+ 
  | table_cache | 2048 | 
  +---------------+-------+ 
  比較合適的值爲: 
  Open_tables / Opened_tables * 100% >= 85% 
  Open_tables / table_cache * 100% <= 95% 




  六、進程使用情況 
  mysql> show global status like ‘Thread%’; 
  +-------------------+-------+ 
  | Variable_name | Value | 
  +-------------------+-------+ 
  | Threads_cached | 46 | 
  | Threads_connected | 2 | 
  | Threads_created | 570 | 
  | Threads_running | 1 | 
  +-------------------+-------+   


      如果我們在MySQL服務器配置文件中設置了thread_cache_size,當客戶端斷開之後,服務器處理此客戶的線程將會緩存起來以響應下一個客 戶而不是銷燬(前提是緩存數未達上限)。Threads_created表示創建過的線程數,如果發現Threads_created值過大的話,表明 MySQL服務器一直在創建線程,這也是比較耗資源,可以適當增加配置文件中thread_cache_size值,查詢服務器 thread_cache_size配置: 
  mysql> show variables like 'thread_cache_size'; 
  +-------------------+-------+ 
  | Variable_name | Value | 
  +-------------------+-------+ 
  | thread_cache_size | 64 | 
  +-------------------+-------+   


      示例中的服務器還是挺健康的。 




  七、查詢緩存(query cache) 
  mysql> show global status like 'qcache%'; 
  +-------------------------+-----------+ 
  | Variable_name | Value | 
  +-------------------------+-----------+ 
  | Qcache_free_blocks | 22756 | 
  | Qcache_free_memory | 76764704 | 
  | Qcache_hits | 213028692 | 
  | Qcache_inserts | 208894227 | 
  | Qcache_lowmem_prunes | 4010916 | 
  | Qcache_not_cached | 13385031 | 
  | Qcache_queries_in_cache | 43560 | 
  | Qcache_total_blocks | 111212 | 
  +-------------------------+-----------+   


       MySQL查詢緩存變量解釋: 
  Qcache_free_blocks:緩存中相鄰內存塊的個數。數目大說明可能有碎片。FLUSH QUERY CACHE會對緩存中的碎片進行整理,從而得到一個空閒塊。 
  Qcache_free_memory:緩存中的空閒內存。 
  Qcache_hits:每次查詢在緩存中命中時就增大 
  Qcache_inserts:每次插入一個查詢時就增大。命中次數除以插入次數就是不中比率。 
  Qcache_lowmem_prunes:緩存出現內存不足並且必須要進行清理以便爲更多查詢提供空間的次數。這個數字最好長時間來看;如果這個數 字在不斷增長,就表示可能碎片非常嚴重,或者內存很少。(上面的 free_blocks和free_memory可以告訴您屬於哪種情況) 
  Qcache_not_cached:不適合進行緩存的查詢的數量,通常是由於這些查詢不是 SELECT 語句或者用了now()之類的函數。 
  Qcache_queries_in_cache:當前緩存的查詢(和響應)的數量。 
  Qcache_total_blocks:緩存中塊的數量。 
  我們再查詢一下服務器關於query_cache的配置: 
  mysql> show variables like 'query_cache%'; 
  +------------------------------+-----------+ 
  | Variable_name | Value | 
  +------------------------------+-----------+ 
  | query_cache_limit | 2097152 | 
  | query_cache_min_res_unit | 4096 | 
  | query_cache_size | 203423744 | 
  | query_cache_type | ON | 
  | query_cache_wlock_invalidate | OFF | 


       +——————————+———–+ 
  各字段的解釋: 
  query_cache_limit:超過此大小的查詢將不緩存 
  query_cache_min_res_unit:緩存塊的最小大小 
  query_cache_size:查詢緩存大小 
  query_cache_type:緩存類型,決定緩存什麼樣的查詢,示例中表示不緩存 select sql_no_cache 查詢 
  query_cache_wlock_invalidate:當有其他客戶端正在對MyISAM表進行寫操作時,如果查詢在query cache中,是否返回cache結果還是等寫操作完成再讀表獲取結果。 
  query_cache_min_res_unit的配置是一柄”雙刃劍”,默認是4KB,設置值大對大數據查詢有好處,但如果你的查詢都是小數據查詢,就容易造成內存碎片和浪費。 
  查詢緩存碎片率 = Qcache_free_blocks / Qcache_total_blocks * 100% 
  如果查詢緩存碎片率超過20%,可以用FLUSH QUERY CACHE整理緩存碎片,或者試試減小query_cache_min_res_unit,如果你的查詢都是小數據量的話。 
  查詢緩存利用率 = (query_cache_size - Qcache_free_memory) / query_cache_size * 100% 
  查詢緩存利用率在25%以下的話說明query_cache_size設置的過大,可適當減小;查詢緩存利用率在80%以上而且Qcache_lowmem_prunes > 50的話說明query_cache_size可能有點小,要不就是碎片太多。 
  查詢緩存命中率 = (Qcache_hits - Qcache_inserts) / Qcache_hits * 100% 
  示例服務器 查詢緩存碎片率 = 20.46%,查詢緩存利用率 = 62.26%,查詢緩存命中率 = 1.94%,命中率很差,可能寫操作比較頻繁吧,而且可能有些碎片。 




  八、排序使用情況 
  mysql> show global status like 'sort%'; 
  +-------------------+------------+ 
  | Variable_name | Value | 
  +-------------------+------------+ 
  | Sort_merge_passes | 29 | 
  | Sort_range | 37432840 | 
  | Sort_rows | 9178691532 | 
  | Sort_scan | 1860569 | 
  +-------------------+------------+   


       Sort_merge_passes 包括兩步。MySQL 首先會嘗試在內存中做排序,使用的內存大小由系統變量 Sort_buffer_size 決定,如果它的大小不夠把所有的記錄都讀到內存中,MySQL 就會把每次在內存中排序的結果存到臨時文件中,等 MySQL 找到所有記錄之後,再把臨時文件中的記錄做一次排序。這再次排序就會增加 Sort_merge_passes。實際上,MySQL 會用另一個臨時文件來存再次排序的結果,所以通常會看到 Sort_merge_passes 增加的數值是建臨時文件數的兩倍。因爲用到了臨時文件,所以速度可能會比較慢,增加 Sort_buffer_size 會減少 Sort_merge_passes 和 創建臨時文件的次數。但盲目的增加 Sort_buffer_size 並不一定能提高速度,見 How fast can you sort data with MySQL?(引自http://qroom.blogspot.com/2007/09/mysql-select-sort.html,貌似被牆) mysql 
  另外,增加read_rnd_buffer_size(3.2.3是record_rnd_buffer_size)的值對排序的操作也有一點的好 處,參見:http://www.mysqlperformanceblog.com/2007/07/24/what-exactly-is- read_rnd_buffer_size/ 




  九、文件打開數(open_files) 
  mysql> show global status like 'open_files'; 
  +---------------+-------+ 
  | Variable_name | Value | 
  +---------------+-------+ 
  | Open_files | 1410 | 
  +---------------+-------+ 
  mysql> show variables like 'open_files_limit'; 
  +------------------+-------+ 
  | Variable_name | Value | 
  +------------------+-------+ 
  | open_files_limit | 4590 | 
  +------------------+-------+   


      比較合適的設置:Open_files / open_files_limit * 100% <= 75% 




  十、表鎖情況 
  mysql> show global status like 'table_locks%'; 
  +-----------------------+-----------+ 
  | Variable_name | Value | 
  +-----------------------+-----------+ 
  | Table_locks_immediate | 490206328 | 
  | Table_locks_waited | 2084912 | 
  +-----------------------+-----------+   


       Table_locks_immediate表示立即釋放表鎖數,Table_locks_waited表示需要等待的表鎖數,如果 Table_locks_immediate / Table_locks_waited > 5000,最好採用InnoDB引擎,因爲InnoDB是行鎖而MyISAM是表鎖,對於高併發寫入的應用InnoDB效果會好些。示例中的服務器 Table_locks_immediate / Table_locks_waited = 235,MyISAM就足夠了。 




  十一、表掃描情況 
  mysql> show global status like 'handler_read%'; 
  +-----------------------+-------------+ 
  | Variable_name | Value | 
  +-----------------------+-------------+ 
  | Handler_read_first | 5803750 | 
  | Handler_read_key | 6049319850 | 
  | Handler_read_next | 94440908210 | 
  | Handler_read_prev | 34822001724 | 
  | Handler_read_rnd | 405482605 | 
  | Handler_read_rnd_next | 18912877839 | 
  +-----------------------+-------------+   


        各字段解釋參見http://hi.baidu.com/thinkinginlamp/blog/item/31690cd7c4bc5cdaa144df9c.html,調出服務器完成的查詢請求次數: 
  mysql> show global status like 'com_select'; 
  +---------------+-----------+ 
  | Variable_name | Value | 
  +---------------+-----------+ 
  | Com_select | 222693559 | 
  +---------------+-----------+   


       計算表掃描率: 
  表掃描率 = Handler_read_rnd_next / Com_select 
  如果表掃描率超過4000,說明進行了太多表掃描,很有可能索引沒有建好,增加read_buffer_size值會有一些好處,但最好不要超過8MB。 
  後記: 
  文中提到一些數字都是參考值,瞭解基本原理就可以,除了MySQL提供的各種status值外,操作系統的一些性能指標也很重要,比如常用的top,iostat等,尤其是iostat,現在的系統瓶頸一般都在磁盤IO上,關於iostat的使用. 




----------------------------------- 
http://hi.baidu.com/jiaofu1127/blog/item/c0d98dd973a3b094a1ec9ca0.html 




下載地址 


http://hackmysql.com/mysqlreport 


用法 


perl mysqlreport --user root --password --socket /tmp/mysql5-1.sock 






Report Header: Line 1 
報表的第一行包含了三樣不同的信息: 
MySQL Server 的版本、自上次啓動後已經過多少時間、目前 Server 的日期與時間。有些人會定時讓系統自動產生報表 
(eg. cron)然後用程序去分析進行分析,此時表頭將可用來協助您辨識出不同時間點的報表。對於那些租用或使用虛擬主機的管理者,表頭可以協助您了 
解自己所需面對的是什麼樣的 Server。MySQL Server 版本可以指出該 Server 有提供或沒有提供那些功能,而它的 
Uptime 則表示該報表具有多大的代表性。Uptime 是重要的指標,可讓您瞭解此份報表所包含的信息是否可能有偏誤,一般來說 Uptime 
最少要有一小時會比較適當,甚至光是一小時其實也還不夠。例如您的 Server 可能已執行了六個小時,但此六小時皆是在使用率最低的午夜,此時產生出 
的報表就很不具有代表性。最理想的情況下,你會希望 MySQL Server 至少已經執行了一整天,這樣子一來你就可以確定報表中的信息已包含了 
Server 負載的高峯與低峯期,而不是隻包含其中之一。在範例報表中 Server 只執行了 34 分鐘,因此該報表的代表性是不足的,但因爲這 
只是用來做範例,也就沒什麼關係。 
Key Report: Lines 3 - 7 
第一個主要報告 
區塊就是 Key Report,因爲 Key(Indexes, 索引)是所有信息中最重要的一項。雖然此報表無法告知您 Server 是否有善用 
Index,但它可以告訴您 Server 對於 Shared Key Buffer 的使用狀態。請注意,這裏所指的 Key Buffer 是指 
MyISAM Storage Engine 所使用的 Shared Key Buffer,InnoDB 所使用的 Key Buffer 並不包 
含在內。 
MySQL Server 支持許多種不同類型的數據表(比較正式的說法是 Storage Engine),你可以將它們想象爲各種不 
同的數據結構,而不同的 Storage Engine 各有其優缺點。其中 MySQL Server 預設是使用 
MyISAM Storage Engine。 
MySQL Server 的 Buffer 大略可分爲二種: 
1. Global Buffer:由所有 Client 所共享的 Buffer 
key_buffer 
innodb_buffer_pool 
innodb_log_buffer 
innodb_additional_mem_pool 
net_buffer ...等等 


2. Thread Buffer:個別的 Connection 所需佔用的 Buffer 
例如: 
sort_buffer 
myisam_sort_buffer 
read_buffer 
join_buffer 
read_rnd_buffer ...等等 


計算 Server 至少需使用的總內存數量的方式爲: 
min_memory_needed = global_buffer + (thread_buffers * max_connection) 
關於 MySQL 的 Cache 機制有一點需要特別注意,各位應該都知道 MyISAM Storage Engine 將每個 table 分成三個 
檔案儲存在硬盤之中,例如若您有一個數據表的名稱爲 example,那麼您就會在硬盤上發現 example.FRM, example.MYD, 
example.MYI 等三個檔案。這三個檔案所儲存的數據如下: 
FRM: 儲存這個數據表的結構 
MYD: Row Data,也就是你存在 example 數據表裏的數據 
MYI: 此數據表的索引接下來是重點: 
當 MySQL 要 Cache 某個資料表時,請問 MySQL 會 Cache 哪些資料? 
答案是: 
MySQL 只會 Cache 索引,也就是 *.MYI 檔案,而 Row Data(*.MYD) 則是交由操作系統來負責 Cache。 
接下來我們再回到 Key Buffer,有個很重要的問題我們一直沒有回答,就是『到底 Key Buffer 要設定多少纔夠呢?』。如前所述, 
MySQL 只會 Cache 索引(*.MYI),因此您只要將數據庫中所有的 MYI 檔案加總起來,你就會知道大概要設爲多少。 
Buffer used: Line 4 
身爲 MySQL 的管理者您通常會問的第一個問題是:『Server 到底用掉了多少 key buffer?』。如果您發現 MySQL 只使用了一小 
部份的 Key Buffer,這並不是什麼需要注意的問題,因爲 MySQL 只會在需要的時候才實際分配與使用 System RAM。也就是說,當 
你設定 MySQL 可使用 512MB 的 RAM 時,並不代表 MySQL 啓動的時候將佔用 512MB 的 RAM(只有在 MySQL 認爲 
需要這麼做的時候纔會)。報表中的第四行(Buffer used)指出 MySQL "曾經" 耗用過的最大內存數量,因此目前 "正在使用" 的內存 
數量有可能少於(甚至大於)這個數字。MySQL 稱此數值爲 "High Water Mark",但在報表的下一行我們將會看到它並不總是如此。無論 
如何,從 Buffer used 我們通常可以看出 key_buffer_size 這個系統變量值是否設定的夠大,如果你的 MySQL 已經使用 
了 80~90% 以上的 Key Buffer,你就應該要調高 key_buffer_size。注意,Buffer used 永遠不會有使用率超 
過 95% 的情況,因爲 MySQL 的官方文件中指出 Share Key Buffer 中有部份將會挪用給內部數據結構使用,因此當 
Buffer used 指出 Share Key Buffer 的使用率高達 95% 時,其實在實務上等於是已使用了 100% 的 
Share Key Buffer。在這個例子中 Server 只使用了 380KB(0.07%) 的 Share Key Buffer,看到這 
裏也許您會判斷 Server 的 Share Key Buffer 是十分充足的,但請勿太早下定論,我們必須要接着考慮報表中的下一行才能做出客觀 
的判斷......。 
Current: Line 5 
mysqlreport 使用 
Key_blocks_unused 這個系統變量來決定目前 MySQL "正在使用" 的 Share Key Buffer 大小,只有在 
MySQL Server 4.1.2 以上的版本纔會有這個功能。如果報表中的上一行(Buffer used)真的有如 MySQL 官方文件中所 
說的是 "High Water Mark",那麼 Current 所載明的數值應該永遠會小於或等於它。但在接下來的例子中我們將會看到,事情並不總 
是如此。目前這臺 Server 已經使用了大約 60MB(12%) 的 Share Key Buffer,這是一個好現象因爲它代表了你的 
Share Key Buffer 仍然十分充足。Current 與 Buffer used 合在一起看即可提供一個很有用的指標,告訴您目前的 
key_buffer_size 是否充足。 
設定 key_buffer_size 的方式也很簡單,只要直接修改 MySQL 的設定檔然後重新啓動 Server 即可。例如若要將 Key Buffer 設定爲 2000MB,則只要在 /etc/my.cnf 中加上: 
[mysqld] 
key_buffer_size=2000M 
Write ratio: Line 6 
索 
引(Indexes, Keys)主要是在內存內(RAM-Based)進行操作的,索引之所以如此有用有部份原因就歸功於它們主要是在 RAM 裏面運 
作,因此擁有極高的存取效能,不像儲存在硬盤中的數據存取速度非常慢。然而,不可否認的是 MySQL 終究還是必須從硬盤中將索引讀入 RAM 或是將 
儲存在 RAM 中的索引寫回硬盤之中。Write ratio 標示着 MySQL 將索引寫入硬盤與 MySQL 將索引寫入 RAM 的比值 
(Write Ratio = MySQL 將索引寫入硬盤的次數 / MySQL 將索引寫入 RAM 的次數)。具有接近於 1 的 
Write Ratio 並不是一件很罕見的事,就像 MySQL 官方手冊中所說的,如果你的 MySQL 最主要的活動是 Update、 
Insert 等等,那麼 Write Ratio 將會很接近於 1。Write Ratio 若大於 1 表示 MySQL 將索引寫入硬盤的次數大 
於將索引寫入 RAM 的次數,很少有 MySQL Server 的 Write Ratio 會大於 1,絕大部份都應該會小於 1,即便是負載非常 
重的 Server。 
Read ratio: Line 7 
Read Ratio 比 
Write Ratio 來得重要一些,它標示了 MySQL 從硬盤讀取索引與從 RAM 讀取索引的比值(Read Ratio = MySQL 
從硬盤讀取索引的次數 / MySQL 從 RAM 讀取索引的次數)。Read Ratio 的值應該要是 0.00 或 0.01,若大於這個值則表 
示 Server 有問題需要進一步的調查,通常此問題的成因是 Share Key Buffer 設得太小造成 MySQL 需要不斷地從硬盤中讀取 
所需要的索引信息,而這個動作是十分沒有效率的並且完全抵消了使用索引可以帶來的好處。在 Server 剛啓動的頭一個小時 Read Ratio 很 
常會出現大於 0.01 的數值,但 Server 執行過一陣子後它應該(也必須)降低至 0.01 或是 0.00。 
Questions Report: Lines 9 - 26 
第 
二個主要的報表區塊,Questions,是第二重要的信息,因爲它可以告訴你 MySQL 到底都在忙些什麼事情。Questions 包含了 
SQL queries 以及 MySQL protocol communications。大部份的人都只在意 Server 每秒可以處理多少查 
詢(Queries Per Second, QPS),但若以整個 Server 的觀點來考慮,QPS 其實是非常不精確的數值,它無法有效的告訴您 
Server 的整體運作狀況。而 Questions 則提供了較完整的信息,讓您一窺 Server 的全貌。 
Total: Line 10 
第 
一個字段單純的記載 MySQL 總共響應過多少查詢,第二個字段則記錄響應的頻率(QPS),當大部份的人說『我的 Server 平均每秒處理 
XXX 個查詢』時,他們指的其實就是第二個字段所記錄的響應頻率。此時你應該要反問他們『在那 XXX 個查詢之中,MySQL 到底做了哪些事 
情?』,接下來 mysqlreport 將可以協助您回答此問題......。 
Distribution of Total Queries (DTQ): Lines 11 - 15 
所有的 Questions 可以大致區分爲五個不同的類別: 
1.Data Manipulation Statements (DMS) 
2.query cache hits (QC Hits) 
3.COM_QUIT 
4.all other Com_ commands 
5.Unknown 
這 
五個類別將會展示在 Lines 11 至 15,但它們的順序是會改變的。mysqlreport 預設是以查詢的總數(第一個字段)來排序,次數越多 
排得越上面,讓您可以快速的分辨出 MySQL 大部份時間都在忙些什麼東西。理想的情況下,你會希望 MySQL 把大部份的時間都花在 DMS 與 
QC Hits 這兩個類別,因爲這兩個類別纔是真正在 "完成正事" 的類別。COM_QUIT、Com_、與 Unknown 也有其存在的必要, 
但它們應該只佔了其中的一小部份。在繼續深入介紹之前,也許你會好奇第三個字段是做什麼用的,它代表了該分類(例如 DMS)佔全部 Queries 的 
百分比;若是在子分類(例如 Select)中,則表示該子分類佔所屬分類(例如 DMS)的百分比。在此範例中 DMS 佔了所有 Queries 的 
82.84%,這是一個很好的現象。 
Data manipulation statements(DMS) 包 
含了:ELECT, INSERT, REPLACE, UPDATE, 與 DELETE(技術上來說,其實不只這幾個類別但 
mysqlreport 只會用到這幾類)。基本上,你可以將 DMS 想成是 MySQL 真正有在做些 "有用的事" 的情況,因此你會希望 
DMS 是 MySQL 最忙着處理的事情。 
QC Hits 
是 MySQL 不需要實際執行 Query 而只要直接從 Query Cache 中即可找到所需數據的次數。擁有高比例的 QC Hits 是讓人 
夢寐以求的事,因爲從 Query Cache 直接存取所需要的數據是十分快速且有效率的。然而大部份的 MySQL Server 因爲各種原因,而 
無法具有非常有效率的 Query Cache。在本範例中 QC Hits 佔了所有 Questions 的 16.91%,這是非常好的情況。然 
而,千萬不要被這個數值給誤導了,在報表中的 38 至 45 行(Query Cache Report)將會告訴您完全不同的狀況。這是一個很好的範 
例,展示了 mysqlreport 可以做爲深入、相互參照與比對的分析工具。當 QC Hits 看來似乎十分完美時,這個 Server 的 
Qeury Cache Report 卻可以明確的告訴您其實事情沒有表面上看起來的那樣完美,我們在稍後會在回到這個問題。 
COM_QUIT 算是比較不重要的類別,若您不是真的很有興趣其實您大可忽略這個類別的內容。 
COM_ 這 
個類別代表着所有 MySQL 所執行過的指令,通常與 MySQL protocol 相關。在正常的情況下,你會希望這個類別所佔的比例越低越好,因 
爲當這個數值很高的時候就表示 MySQL 正忙碌於無關緊要的事情上。若這個數值很高通常代表 MySQL 正遭遇到某些很奇怪的問題,當我們深入討論 
COM_ 的子類別的時候,我們會在回來探討這個問題。 
Unknown 是 
推論出來的類別,在理想的狀況下,之前所述的四個分類加總起來應該要等於 Questions 總數,但它們通常不會剛好等於。這是因爲有些 
Questions MySQL 在處理時會增加 Total Questions 的計數器,但卻沒有相對應的系統變量用來記錄所執行過的 
Questions。在不同的 Server 上這個數值的變異很大,在有些 Server 上這個數值非常的高,在有些 Server 上則非常的 
低,但在大部份的情況下它應該要維持在很低的水平纔是。如果這個數值非常的高,可能代表 MySQL Server 有什麼地方出了問題。 
Slow: Line 16 
第 16 
行非常的重要:它記錄了 MySQL 總共執行了多少次 Slow Query。Slow Query 就是指執行所需時間超過某個時間區間的 
Query,例如執行超過 10 秒的 Query。用來判定是否爲 Slow Query 的時間區間是可以透過 long_query_time 
這個系統變量來設定的,MySQL 預設 long_query_time 爲 10 秒,但通常我們會將它設定爲 5 秒。在最理想的情況下,我們會希 
望看到這個數值等於零,但通常這數值不會是零。一般來說 Slow Query 佔 Total Questions 的比例應該要低於 0.05, 
Slow Query 的次數(第一個字段)本身不是很重要,真正需要注意的是 Slow Query 佔 Total Questions 的比例,若 
這比例偏高就代表 Server 有些問題需要解決。第四個字段中的『%DMS: 』表示 Slow Query 在所有 DMS 中所佔的比例。 
DMS: Lines 17 - 22 
DMS 
的子分類項目可以告訴我們,這臺 MySQL Server 是屬於哪一個類型的 MySQL Server,例如它是着重在 SELECT 操作或是 
INSERT 操作,大部份的 MySQL Server 都是着重在 SELECT 操作。知道某臺 Server 是屬於哪一個類型的 
MySQL Server 有助於我們思考報表中的其它信息,例如一臺着重在 SELECT 操作的 MySQL Server 的 
Write Ratio 應該會非常的接近 1,並有着較高的 Lock 時間。同時它也隱含了一個意義,就是也許你可以考慮使用
InnoDB Storage Engine,因爲 MySQL 預設採用的 MyISAM Storage Engine 所提供的 Lock 層級 
只有 Table Lock(只能針對整個數據表鎖定),而 InnoDB 則提供 Row Lock 層級的鎖定機制(可只針對特定的 ROW 進行鎖 
定,減少等待時間)。若是着重在 SELECT 操作的 Server,它的 Read Ratio 應該會接近於零,並有着非常低的 
Table Lock 時間。 
在範例中的 Server 是屬於着重在 SELECT 操作的 Server:65.72% 的 
Questions 是 SELECT(第三個字段)、79.33% 的 DMS Questions 是 SELECT(第四個字段)。很明顯的,這 
是臺着重在 SELECT 操作的 Server,知道了此項事實之後,我們纔有辦法對其進行最佳化。 
Com_: Lines 23 - 26 
這個子分類只有在它的值偏高的時候才需要注意,因爲過高的值表示 MySQL 正在忙着處理 "程序方面的東西",而不是響應使用者的查詢。對大部份的 Server 來說這裏應該都不會出現偏高的數值,但您最好還是定期的檢查一下。 
SELECT and Sort Report: Lines 28 - 36 
大 
致上來說,你只要注意第 29 行與第 31 行:Scan 與 Full Join。Scan 指的是有多少 SELECT statements 造 
成 MySQL 需要進行 Full Table Scan。Full Join 的意思與 Scan 差不多,但它是適用在多個 Tables 相互 
Join 在一起的情況。這二種情況的執行效能都非常的差,因此原則上你會希望這兩個數值越低越好。但這也不是絕對的,仍然要考慮實際的情況,例如雖然 
Server 有很高比例的 Scan,但若這些 Scan 都是針對一些只有幾十筆數據的 table,那麼相對而言它依然是十分有效率的;但反之, 
若這些 Scan 是針對具有上百萬筆數據的 table,那麼就會嚴重影響系統效能。 
Query Cache Report: Lines 38 - 45 
Query Cache Report 只有在 MySQL 有支持 Query Cache,以及 Query Cache 功能有開啓的情況下纔會有這段信息出現。 
Memory usage: Line 39 
此項目指出 Query Cache 的使用狀況,若系統已達到 Query Cache 的上限則會連帶影響到 Prunes Value,因爲當配給的 Memory 不足時,MySQL 必須不斷地消除 RAM 中較不常使用的數據以挪出空間擺放新的數據。 
Block Fragmnt: Line 40 
這 
個數值越高表示 Query Cache 的 Fragment 狀況越嚴重,通常它會界於 10%~20% 之間。在此範例中 
Block Fragmnt 爲 13.05%,這是可接受的情況,當然你也可以調整 query_cache_min_res_unit 的值來降低 
Block Fragmnt。 
Hits, Inserts, Prunes: Lines 41 - 43 
Hits 
是這三個數值中最重要的一項,因爲它指出有多少 SELECT statements 是可直接從 Query Cache 裏面取得所需的信息,此數值 
越高就越好。Inserts 和 Prunes 最好是從第 44 行的比值來觀察比較容易理解。雖然 Prunes 的值偏高可能代表着 
Query Cache 設得不夠大,但並不一定是如此。在本例中只有 55% 的 Query Cache 被使用,有着相對而言算低的 
fragmentation 值,但 Prunes 值偏高,Prunes 的值(16/s)是 QC Hits 的兩倍。你可以想象這臺 
Server 的 Query Cache 是一顆蘋果樹,它的樹枝被剪去的速度比你採收蘋果的速度還快。 
Insrt:Prune and Hit:Insert Ratios: Lines 44 - 45 
第 44 
行中的 Insert 與 Prune 的比值可顯示 Query Cache 的揮發性。在一個高度穩定的 Query Cache 中,Insrt 
的值應該要高於 Prune 的值;反之,在一個揮發性較高(較不穩定)的 Query Cache 中,這個比值將會是 1:1 或是偏重在 
Prune 那方,這表示 Query Cache 中的數據有可能在使用到之前就已經被清除了。我們會希望擁有一個穩定的 Query Cache, 
因爲穩定的 Query Cache 表示那些被 Cache 在 Query Cache 中的資料會常被用到。高揮發性(較不穩定)的 
Query Cache 代表兩件事情:第一,Query Cache 設得太小,需要加大。第二,MySQL 正試圖要 cache 所有的東西,甚 
至是那些其實並不需要 cache 的數據。若是第一種狀況,只要單純的加大 Query Cache 即可。若是第二種情況,可能是 MySQL 試圖 
要去 cache 所有可以 cache 的數據,你可以使用 SQL_NO_CACHE 來明確的告訴 MySQL 什麼資料是你不想要 cache 
的。 
Hit 與 Insert 的比值代表着 Query Cache 的有效性,理想的情況是我們新增了一些 Qeury 到 
Query Cache 中,然後希望得到許多 Hits。因此若是這個 Query Cache 是有效率的,那麼該比值應該要偏重在左方。若比值是 
偏重在 Insert 那方,那麼這個 Query Cache 的揮發性就太高了。考慮以下這個比值,若 Hit:Insert 爲 1:1,那就表示 
Query Cache 中的數據只使用了一次就被清除掉了,換句話說,我們放進去的數據比我們從裏面拿出來的數據還多,這樣一來就失去了使用 
Query Cache 的意義。回想我們前面所提過的,雖然在本範例中 QC Hit 在全部的 Questions 中佔了很高的比例,但實際上我 
們可以發現 QC 的有效性其實是很低的(Hit:Insert 的比值偏重在 Insert 那方)。若造成這個現象的原因是 MySQL 正試圖 
cache 所有的東西,那麼將 Cache 模式改爲 DEMAND 或許可以解決此問題。 
Table Locks Report: Lines 47 - 49 
這 
個部份包含了兩項信息:第一項是 Waited,代表 MySQL 需要等待以取得 table lock 的次數。第二項是 Immediate,表示 
MySQL 不需要等待即可立刻取得 table lock 的次數。對數據庫來說『等待』幾乎可以肯定是一件很不好的事情,因此 Waited 的值 
應該要越小越好。最具有代表性的是第三個字段(Waited 佔所有 table lock 的百分比),這個數值應該要小於 10%,大於這個值就表示 
table/query 的索引設計不良或是有過多的 Slow Query。 
Tables Report: Lines 51 - 53 
Tables Report 
同樣包含了二項信息:第一是 Open,顯示目前正開啓的 table 數量、總共可開啓的最大數量,以及 Table Cache 的使用狀況。第二是 
Opend,表示截至目前爲止 MySQL 總共開啓過的 Table 數量,以及除上 Uptime 後的比值。這裏有兩件事值得注意:首先是 
Table Cache 的使用狀況,100% 的 Table Cache 使用率並不是一件壞事但你可以試着調大 Table Cache 以增進 
效能。第二是 MySQL 開啓 Table 的平均速率,若這個值很高則表示您的 table_cache 設得太小了,需要調大一些。一般來說, 
MySQL 開啓 Table 的平均速率最好是小於 1/s。但大於這個數值也不一定就是壞事,有些調校良好且運作的十分有效率的 
MySQL Server 其值爲 7/s 並使用了 100% 的 Table Cache。 
Connections Report: Lines 55 - 57 
Connections Report 
所代表的意義與 Tables Report 相似,請各位以此類推。比較需要注意的是:若你發現 Connections 的使用率接近 100%,也 
許你會想調大 max_connections 的值以允許 MySQL 的 Client 建立更多聯機。然而,這通常是一種錯誤。我們常常可以發現很 
多網絡上的數據會教我們要調大 max_connections,但卻從來沒有給一個明確的理由。事實上,max_connections 的默認值 
(100),就算是對於負載十分沉重但有良好調校過的 Server 都已十分足夠。MySQL 對於單一聯機的數據處理通常只需要零點幾秒的時間即可完 
成,就算是最大隻能使用 100 個聯機也夠讓你用上很長一段時間。若是您的 Server 有着非常高的最大聯機數(max connections) 
或是單一聯機需要很長時間纔可完成,那麼問題八成不是 max_connections 的值不夠大而是在別的地方,例如 slow queries、索 
引設計不良、甚至是過於緩慢的 DNS 解析。在您將 max_connections 的值調到 100 以上之前,您應該要先確定真的是因爲 
Server 過於忙碌而需要調高此數值,而不是其它地方出了問題。每秒平均聯機數有可能會很高,事實上,若這個值很高而且 Server 的運作十分 
順暢,那麼這通常會是一個好現象,無需擔心。大部份 Server 的每秒平均聯機數應該都會低於 5/s。 
Created Temp Report: Lines 59 - 62 
MySQL 
可以建立暫時性的數據表,它可建立在硬盤中、檔案裏、或是 RAM 之中,而 Created Temp Report 則提供了相關的數據供您參考。這 
些數據大多是相對而言,沒有一定的標準,但將暫時性的數據表建立在硬盤中是十分沒有效率的,因此 Disk table 的值最好是三者中最小的一個。當 
暫時性的數據表被建立在硬盤中,表示此數據表沒有辦法被放進 RAM 裏面(因爲 tmp_table_size 的值設得不夠大)。 
Threads, Aborted, Bytes Reports: Lines 64 - 76 
這 
幾個部份大多沒什麼好解釋的,只有一個項目值得特別說明:第 66 行的最後一個字段(%Hit)。每一個連接到 MySQL 的聯機都是由不同的 
Thread 來處理,當 MySQL 啓動時會預先建立一些 Threads 並保留在 Thread Cache 中,如此一來 MySQL 就不 
用一直忙着建立與刪除 Threads。但當每秒最大聯機數大於 MySQL 的 Thread Cache 時,MySQL 就會進入 
Thread Thrash 的狀態:它不斷地建立新的 Threads 以滿足不斷增加的聯機的需求。當 Thread Thrash 發生時,% 
Hit 的數值就會降低。在本範例中 %Hit 的值爲 0.05%,這是非常不好的,因爲它表示幾乎每一個新進來的聯機都會造成 MySQL 建立新的 
Thread。我們可以看到在此範例中造成此現象的原兇就在第 66 行的第一個字段,我們可以發現 Thread Cache 的值爲 0,因此 
thread_cache_size 的值需要調大。 
話說回來,究竟 %Hit 接近於零真的有什麼關係嗎?Jeremy Zawondy 曾 
在部落格上說到:Thread caching 並不是我們最需要關心的問題,但當你解決了所有其它更嚴重的問題之後,它就會是最嚴重的問題 




使用 show full processlist 可以打印出當前執行的查詢語句. 




---------------------配置查詢慢的語句------------------------------ 
mysql監控slow log日誌文件: 
[mysqld] 
#log-slow-queries = /data/mylog/mysql_slow.log 
slow-query-log 
slow-query-log-file = /data/mylog/mysql_slow.log 
long-query-time = 5 


===========執行=== 
mysqlsla -lt slow ./mysql_slow.log > sla.txt       
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章