MySQL查詢優化講座之管理員的優化措施

  前面的部分中講解的優化措施都是沒有特權的MySQL用戶能夠執行的。可以控制MySQL服務器或計算機的系統管理員能夠執行額外的優化措施。例如,有些服務器參數附屬於查詢處理過程,並且是可以調整的,而且某些硬件配置因素對查詢處理速度有直接的影響。在很多情況下,這些優化措施提高瞭整個服務器的性能,因此可以讓所有的MySQL用戶都受益。


  一般來說,當你執行管理員優化的時候,應該緊記以下規則:


  · 訪問內存中的數據快於訪問磁盤上的數據。


  · 盡量把數據保存在內存中可以減少磁盤操作。


  · 保留索引中的信息比保留數據記錄的內容更重要。


  我們在後面將討論如何應用這些規則。


  增加服務器緩存的大小。服務器擁有很多參數(系統變量),你可以改變這些參數來影響服務器的操作。其中的幾個參數直接地影響查詢處理的速度。你可以改變的最重要的參數是數據表緩存的大小和存儲引擎用於緩沖索引操作信息的緩存大小。如果你擁有可用的內存,就把它分配給服務器的緩存,以允許信息存儲在內存中並減少磁盤操作。這會有很好的效果,因為訪問內存中的信息比從磁盤讀取信息的速度快得多。


  · 當服務器打開表文件的時候,它試圖保持這些文件的打開狀態,以減少打開文件操作的數量。為瞭實現這樣的功能,它在表緩存中維護打開文件的信息。table_cache系統變量控制著這個緩存的大小。如果服務器訪問瞭大量的表,表緩存就會被填滿,並且服務器會關閉那些有一段時間沒有使用的表,為打開新表留出空間。你可以通過檢查Opened_tables狀態指示器來訪問表緩存的效果:


SHOW STATUS LIKE ’Opened_tables’;


  Opened_tables顯示瞭某個數據表必須打開的次數(因為它還沒有打開)。這個值也顯示為mysqladmin狀態命令的輸出信息中的Opens值。如果這個數字是穩定的或緩慢增長,那麼它的設置可能是正確的。如果這個數字增長得很快,就意味著這個緩存太小瞭,必須經常關閉數據表來為打開其它的數據表留出空間。如果你擁有文件描述信息,增加表緩存大小將減少數據表打開操作的數量。


  · MyISAM存儲引擎使用鍵緩沖來保持與索引相關的操作的索引信息塊。它的大小是由key_buffer_size系統變量控制的。這個值越大,MySQL就一次性在內存中保持更多的索引信息塊,可以增加在內存中(而不用從磁盤上讀取新的信息塊)找到鍵值的可能性。鍵緩存的默認大小是8MB。如果你擁有很多的內存,這是一個很保守的值,你可以直接增加它的大小,並且會看到基於索引的檢索、索引的建立和修改操作的性能有很大改善。


  在MySQL 4.1以上版本中,你可以為MyISAM數據表建立附加的鍵緩存,並指定某些表使用它們。這樣可以幫助提高這些數據表上的查詢處理速度。


  · InnoDB和BDB引擎擁有自己的用於緩沖數據和索引值的緩存。它們的大小是由innodb_buffer_pool_size和bdb_cache_size變量控制的。InnoDB引擎還維護瞭一個日志緩沖。innodb_log_buffer_size變量可以控制它的大小。


  · 另一個專用的緩存是查詢緩存,我們在”使用查詢緩存”部分中解釋。


  當你改變這些參數值的時候,應該遵循下面一些原則:


  · 每次隻改變一個參數。如果你一次改變多個相互獨立的變量,那麼就很難評估每種改變的效果瞭。


  · 逐漸地增加系統變量值。根據理論,數量越多,性能越好,但是如果你使某個變量變得太大瞭,有可能造成系統資源匱乏,導致逆向效果,降低速度。


  · 不要在運行業務MySQL數據庫的服務器上做調整參數的實驗,最好建立一個獨立的測試服務器。


  · 為瞭大致瞭解哪種參數變量可能適合自己的系統,你可以查看MySQL發佈文檔中包含的my-small.cnf、my-medium.cnf、my-large.cnf和my-huge.cnf選項文件(在Unix系統上,你可以在源發佈文件的支持文件目錄和二進制發佈文件的共享目錄總找到這些文件。在Windows上,它們位於基本的安裝目錄中,其擴展名可能是.ini)。這些文件可能讓你知道最好改變服務器上的那些參數以適應不同的使用層次,並且為這些參數提供瞭一些典型值。


  用於提高服務器的操作性能的其它一些策略還包括:


  禁止不需要的存儲引擎。服務器不會為禁止的引擎分配任何內存,因此我們可以利用這一點。如果從源文件建立MySQL,那麼在配置的時候,大多數存儲引擎就可以被排除在服務器之外。對於那些包含在服務器中的引擎來說,使用適當的啟動選項可以在運行時禁止其中的大多數。
保持授權表許可的簡單性。盡管服務器在內存中緩存瞭授權表內容,但是如果你在tables_priv或columns_priv表中有一些數據行的話,服務器就必須為每個查詢語句檢查表層次和列層次的權限。如果這些表是空的,那麼服務器就能優化自己的權限檢查過程,略過這些層次。


  如果你從源文件建立MySQL,那麼就把它配置為使用靜態類庫,而不要使用共享類庫。使用共享類庫的動態二進制文件節約磁盤空間,然而靜態二進制文件速度更快。但是,如果你使用瞭用戶自定義函數(UDF)機制,那麼有些系統要求使用動態鏈接。在這類系統上,靜態二進制文件不能工作。


  使用MyISAM鍵緩存


  當MySQL執行某個利用瞭MyISAM數據表索引的語句的時候,它會使用鍵緩存來保持索引值。這種緩存減少瞭磁盤I/O:如果在緩存中找到瞭某個數據表需要的鍵值,就不需要再次從磁盤中讀取。不幸的是,這種鍵緩存是有限的,並且在默認情況下,它是所有的MyISAM數據表共享使用的。如果在鍵緩存中沒有找到鍵值並且鍵緩存是滿的,爭用將會導致:必須丟棄緩存中的某些值,為新值留出空間。如果下次需要那些已經被丟棄的值,就必須再次從磁盤上讀取。


  如果你很倚重MyISAM數據表,那麼把它的鍵保存在內存中效果會很好,但是緩存中的爭用卻會導致相反的效果。從同一張表或不同的表讀取數據都可能引起爭用。你可以通過把鍵緩存設置成足以保存某個特定數據表的全部索引,從而避免同一張數據表的爭用,但是其它數據表的鍵仍然需要爭用緩存空間。


  MySQL 4.1以上版本為這個問題提供瞭一種解決方案:它支持我們建立多個鍵緩存,並允許我們把某張數據表的索引指定並且預先裝入某個緩存。如果你的數據表使用得很頻繁,並且你有足夠的內存,能夠把它的索引載入緩存中,那麼這種操作就是有用的。這種能力允許你同時避免同一張表和不同的表的爭用:建立一個足夠大的緩存,讓它保存數據表的全部索引,並且指定該緩存專門用於那張數據表。在鍵被載入緩存之後,不在需要磁盤I/O操作。同時,鍵值永遠不會被丟棄,對數據表的鍵的查看操作可以在內存中完成。


  下面的例子顯示瞭如何為sampdb數據庫的member數據表建立一個鍵緩存,該緩存的名稱是member_cache,大小為1MB。執行這些指令的時候,你必須有超級(SUPER)權限。


  1.建立一個足夠容納數據表索引的獨立的緩存:


mysql> SET GLOBAL member_cache.key_buffer_size = 1024*1024;


  2.給數據表指定鍵緩存:


mysql> CACHE INDEX member IN member_cache;
+—————+——————–+———-+———-+
| Table | Op | Msg_type | Msg_text |
+—————+——————–+———-+———-+
| sampdb.member | assign_to_keycache | status | OK |
+—————+——————–+———-+———-+


  3.把數據表索引預先讀入它的鍵緩存中:


mysql> LOAD INDEX INTO CACHE member;
+—————+————–+———-+———-+
| Table | Op | Msg_type | Msg_text |
+—————+————–+———-+———-+
| sampdb.member | preload_keys | status | OK |+—————+————–+———-+———-+


  如果你希望把其它的數據表載入同一個緩存中,或者為其它的數據表建立鍵緩存,上面的操作就足夠瞭。


  使用查詢緩存


  MySQL服務器可以使用查詢緩存來提高那些重復執行的SELECT語句的處理速度。它對性能的提高通常都是驚人的。查詢緩存的工作方式如下所示:


  · 第一次執行某條SELECT語句的時候,服務器記住該查詢的文本內容和它返回的結果。


  · 服務器下一次碰到這個語句的時候,它不會再次執行該語句。作為代替,它直接從查詢緩存中的得到結果並把結果返回給客戶端。


  · 查詢緩存是基於服務器所接收到的查詢字符串的文本內容的。如果某些查詢的文本完全相同,那些它就認為這些查詢是相同的。如果某些查詢的字符不同,或者來自那些使用瞭不同的字符集或通訊協議的客戶端,那麼它會認為這些查詢是不同的。同樣,如果某些查詢采用其它的功能相當、但是實際上沒有指向相同的數據表(例如引用瞭不同的數據庫中的同名數據表),那麼它們也是不同的。


  · 當數據表被更新瞭之後,涉及到該數據表的任何緩存查詢都變成無效的,並且會被丟棄。這可以防止服務器返回過期的結果。


  在默認情況下,MySQL對查詢緩存的支持是內建的。如果你不希望使用這種緩存,並且想避免它所導致的性能開銷,可以使用–without-query-cache選項來運行配置腳本建立服務器。


  如果需要檢測某個服務器是否支持查詢緩存,可以檢查它的have_query_cache系統變量:


mysql> SHOW VARIABLES LIKE ’have_query_cache’;
+——————+——-+
| Variable_name | Value |
+——————+——-+
| have_query_cache | YES |
+——————+——-+


  對於那些支持查詢緩存的服務器來說,緩存的操作是基於三個系統變量值的:


 

發佈留言