介紹了從幾方面優化MYSQL從而獲得性能的方法。 最佳化是一項複雜的任務,因為它最終需要對整個系統的理解.當用你的系統/應用的小知識做一些局部優化是可能的時候,你越想讓你的系統更優化,你必須知道它也越多. 因此,本章將試圖解釋並給出優化MySQL的不同方法的一些例子.但是記住總是有某些(逐漸變難)是系統更快的方法留著去做. 為了使一個系統更快的最重要部分當然是基本設計.你也需要知道你的系統將做這樣的事情,那就是你的瓶頸. 最常見的瓶頸是:
磁碟尋道.磁碟花時間找到一個資料,用在1999年的現代磁碟其平均時間通常小於10ms,因此理論上我們能大約一秒尋道1000 次.這個時間用新磁碟提高很慢並且很難對一個表格優化.優化它的方法是將資料散佈在多個磁碟上. 當磁碟在我們需要讀取資料的正確位置時,磁碟讀/寫.用1999年的現代,一個磁碟傳輸類似10-20Mb/s .這必尋道更容易優化,因為你能從多個磁碟並行地讀. CPU週期.當我們讀數據進內存時,(或如果它已經在那裡)我們需要處理它以達到我們的結果.當我們有相對記憶體較小的表時,這是最常見的限制因素,但是用小表速度通常不是問題. 記憶體頻寬.當CPU需要超出適合cpu快取的資料時,快取頻寬就成為記憶體的一個瓶頸.這是對大多數系統的一個不常見的瓶頸但是你應該知道它. 10.2 系統/編譯時和啟動參數的調節我們以系統級的東西開始,因為這些決策的某一些很早就做好了.在其他情況下,快速瀏覽這部分可能就夠了,因為它對大收穫並不重要,但是有一個關於在這個層次上收穫有多大的感覺總是好的. 使用的缺省OS確實重要!為了最大程度地使用多CPU,應該使用Solaris(因為線程工作得確實不錯)或Linux(因為2.2本的核心又確實不錯的SMP支持).而且在32位的機器上,Linux缺省有2G的文件大小限制.當新的文件系統被釋出時( XFS ),希望這不久被修正. 因為我們沒在很多平台上運行生產MySQL,我們忠告你在可能選擇它前,測試你打算運行的平台.
其他建議:
如果你有足夠的RAM,你能刪除所有交換設備.一些操作系統在某些情況下將使用一個SWAP設備,即使你有空閒的內存. 使用--skip -locking的MySQL選項避免外部鎖定.注意這將不會影響MySQL功能,只要它只運行在一個伺服器上.只要在你運行myisamchk以前,記得要停掉伺服器(或鎖定相關部分).在一些系統上這個開關是強制的,因為外部鎖定不是在任何情況下都工作.當用MIT-pthreads編譯時,-- skip-locking選項缺省為打開(on),因為flock()沒在所有的平台上被MIT-pthreads充分支持.唯一的情況是如果你對同一資料執行MySQL伺服器(不是客戶),你不能使用--skip-locking之時,否則對沒有先清掉(flushing)或先鎖定mysqld伺服器的表上運行myisamchk.你仍然能使用LOCK TABLES/ UNLOCK TABLES,即使你正在使用--skip-locking.
編譯和連結怎麼會影響MySQL的速度
大多數下列測試在Linux上並用MySQL基準進行的,但是它們應該對其他操作系統和工作負載給出一些指示. 當你用-static鏈接時,你得到最快的可執行文件.使用Unix套接字而非TCP/IP連接一個資料庫也可給出好一些的性能. 在Linux上,當用pgcc和-O6編譯時,你將得到最快的代碼.為了用這些選項編譯“sql_yacc.cc”,你需要大約200M內存,因為gcc/pgcc需要很多內存使所有函數嵌入(inline).在配置MySQL時,你也應該設定CXX=gcc以避免包括libstdc++庫(它不需要). 只通過使用一個更好的編譯器或較好的編譯器選項,在應用中你能得到一個10-30%的加速.如果你自己編譯SQL伺服器,這特別重要! 在Intel上,你應該例如使用pgcc或Cygnus CodeFusion編譯器得到最大速度.我們已經測試了新的Fujitsu編譯器,但是它是還沒足夠不出錯來優化編譯MySQL.
這裡是我們做過的一些測量表:
如果你以-O6使用pgcc並且編譯任何東西,mysqld伺服器是比用gcc快11%(用字串99的版本). 如果你動態地連結(沒有-static),結果慢了13%.注意你仍能使用一個動態連接的MySQL庫.只有伺服器對效能是關鍵的. 如果你使用TCP/IP而非Unix套接字,結果慢7.5%. 在一個Sun SPARCstation 10上,gcc2.7.3是比Sun Pro C++ 4.2快13%. 在Solaris 2.5.1上,在單一處理器上MIT-pthreads比帶原生線程的Solaris慢8-12%.以更多的負載/cpus,差別應該變得更大. 由TcX提供的MySQL-Linux的分送用pgcc編譯並靜態連結.
如前面所述,磁碟尋道是一個效能的大瓶頸.當資料開始成長以致快取變得不可能時,這個問題變得越來越明顯.對大資料庫,在那你或多或少地要隨機存取資料,你可以依靠你將至少需要一次磁碟尋道來讀取並且幾次磁碟尋道寫入.為了使這個問題最小化,使用有低尋道時間的磁碟. 為了增加可用磁碟軸的數量(並且從而減少尋道開銷),符號聯接檔案到不同磁碟或分割磁碟是可能的. 使用符號連接這意味著你將索引/資料檔案符號從正常的資料目錄連結到其他磁碟(那也可以被分割的).這使得尋道和讀取時間更好(如果磁碟不用於其他事情).見10.2.2.1 使用資料庫和表的符號連結. 分割分割意味著你有許多磁碟並把第一塊放在第一個磁碟上,在第二塊放在第二個磁碟上,並且第n塊在第(n mod number_of_disks)磁碟上,等等.這意味著,如果你的正常資料大小於分割大小(或完美地排列過),你將得到較好一些的性能.注意,分割是否很依賴於OS和分割大小.因此用不同的分割大小測試你的應用程序.見10.8 使用你自己的基準.注意對分割的速度差異很依賴參數,取決於你如何分割參數和磁碟數量,你可以得出以數量級的不同.注意你必須選擇為隨機或順序訪問優化. 為了可靠,你可能想要使用襲擊RAID 0+ 1(分割+鏡像),但是在這種情況下,你將需要2*N個驅動器來保存N個驅動器的數據.如果你有錢,這可能是最好的選擇!然而你也可能必須投資一些捲管理軟體投資以高效地處理它. 一個好選擇是讓稍重要的資料(它能再生)上存在RAID 0磁碟上,而將確實重要的資料(像主機資訊和日誌檔案)存在一個RAID 0+ 1或RAID N磁碟上.如果因為更新奇偶位你有許多寫入,RAID N可能是一個問題. 你也可以對資料庫使用的檔案系統設定參數.一個容易的改變是以noatime選項掛裝檔案系統.這是它跳過更新在inode中的最後訪問時間,而且這將避免一些磁碟尋道.
你可以從資料庫目錄移動表和資料庫到別處,並且用連結到新地點的符號代替它們.你可能想要這樣做,例如,轉移一個資料庫到有更多空閒空間的一個檔案系統. 如果MySQL注意到一個表格是符號連結,它將解析符號連結並且使用其實際指向的表,它可工作在支援realpath()呼叫的所有系統上(至少Linux和Solaris支援realpath())!在不支援realpath()的系統上,你應該不同時通過真實路徑和符號鏈接訪問表!如果你這樣做,表在任何更新後將不一致. MySQL缺省不支持數據庫鏈接.只要你不在數據庫之間做一個符號鏈接,一切將運作正常.假定你在MySQL資料目錄下有一個資料庫db1,並且做了一個符號連結db2指向db1:
shell&> cd /path/to/datadir
shell&> ln -s db1 db2
現在,對在db1中的任一表tbl_a,在db2種也好像有一個表tbl_a.如果一個線程更新db1.tbl_a並且另一個線程更新db2.tbl_a,將有問題. 如果你確實需要這樣,你必須改變下列在「mysys/mf_format.c」中的程式碼:
if (!lstat(to,&stat_buff)) /* Check if it's a symbolic link */
if (S_ISLNK(stat_buff.st_mode) && realpath(to,buff))
把程式碼改變為這樣:
if (realpath(to,buff))