MySQL優化全攻略-相關數據庫命令

接下來我們要討論的是數據庫性能優化的另一方面,即運用數據庫服務器內建的工具輔助性能分析和優化。

▲ SHOW

執行下面這個命令可以了解服務器的運行狀態:

mysql >show status;

該命令將顯示出一長列狀態變量及其對應的值,其中包括:被中止訪問的用戶數量,被中止的連接數量,嘗試連接的次數,並發連接數量最大

值,以及其他許多有用的信息。這些信息對於確定係統問題和效率低下的原因是十分有用的。

SHOW命令除了能夠顯示出MySQL服務器整體狀態信息之外,它還能夠顯示出有關日誌文件、指定數據庫、表、索引、進程和許可權限表的寶貴

信息。請訪問http://www.mysql.com/doc/S/H/SHOW.html了解更多信息。

▲ EXPLAIN
EXPLAIN能夠分析SELECT命令的處理過程。這不僅對於決定是否要為表加上索引很有用,而且對於了解MySQL處理複雜連接的過程也很有用。

下面這個例子顯示瞭如何用EXPLAIN提供的信息逐步地優化連接查詢。 (本例來自MySQL文檔,見

http://www.mysql.com/doc/E/X/EXPLAIN.html。原文寫到這裡似乎有點潦草了事,特加上此例。)

假定用EXPLAIN分析的SELECT命令如下所示:
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,
       tt.ProjectReference, tt.EstimatedShipDate,
       tt.ActualShipDate, tt.ClientID,
       tt.ServiceCodes, tt.RepetitiveID,
       tt.CurrentProcess, tt.CurrentDPPerson,
       tt.RecordVolume, tt.DPPrinted, et.COUNTRY,
       et_1.COUNTRY, do.CUSTNAME
     FROM tt, et, et AS et_1, do
     WHERE tt.SubmitTime IS NULL
       AND tt.ActualPC = et.EMPLOYID
       AND tt.AssignedPC = et_1.EMPLOYID
       AND tt.ClientID = do.CUSTNMBR;

  
SELECT命令中出現的表定義如下:

※表定義

表列列類型
tt ActualPC CHAR(10)
tt AssignedPC CHAR(10)
tt ClientID CHAR(10)
et EMPLOYID CHAR(15)
do CUSTNMBR CHAR(15)
  

※索引

表索引
tt ActualPC
tt AssignedPC
tt ClientID
et EMPLOYID (主鍵)
do CUSTNMBR (主鍵)
※tt.ActualPC值分佈不均勻

在進行任何優化之前,EXPLAIN對SELECT執行分析的結果如下:
table type possible_keys key key_len ref rows Extra
et ALL PRIMARY NULL NULL NULL 74
do ALL PRIMARY NULL NULL NULL 2135
et_1 ALL PRIMARY NULL NULL NULL 74
tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872
    range checked for each record (key map: 35)

  
每一個表的type都是ALL,它表明MySQL為每一個表進行了完全連接!這個操作是相當耗時的,因為待處理行的數量達到每一個表行數的乘積!

即,這裡的總處理行數為74 * 2135 * 74 * 3872 = 45,268,558,720。

這裡的問題之一在於,如果數據庫列的聲明不同,MySQL(還)不能有效地運用列的索引。在這個問題上,VARCHAR和CHAR是一樣的,除非它們

聲明的長度不同。由於tt.ActualPC聲明為CHAR(10),而et.EMPLOYID聲明為CHAR(15),因此這裡存在列長度不匹配問題。

為了解決這兩個列的長度不匹配問題,用ALTER TABLE命令把ActualPC列從10個字符擴展到15字符,如下所示:
mysql > ALTER TABLE tt MODIFY ActualPC VARCHAR(15);

  

現在tt.ActualPC和et.EMPLOYID都是VARCHAR(15)了,執行EXPLAIN進行分析得到的結果如下所示:
table type possible_keys key key_len ref rows Extra
tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used
do ALL PRIMARY NULL NULL NULL 2135
    range checked for each record (key map: 1)
et_1 ALL PRIMARY NULL NULL NULL 74
    range checked for each record (key map: 1)

et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1

  
這還算不上完美,但已經好多了(行數的乘積現在少了一個係數74)。現在這個SQL命令執行大概需要數秒鐘時間。

為了避免tt.AssignedPC = et_1.EMPLOYID以及tt.ClientID = do.CUSTNMBR比較中的列長度不匹配,我們可以進行如下改動:
mysql > ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
            MODIFY ClientID VARCHAR(15);

  
現在EXPLAIN顯示的結果如下:
table type possible_keys key key_len ref rows Extra
et ALL PRIMARY NULL NULL NULL 74
tt ref AssignedPC,ClientID,ActualPC ActualPC 15 et.EMPLOYID 52 where used
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1

  
這個結果已經比較令人滿意了。
餘下的問題在於,默認情況下,MySQL假定tt.ActualPC列的值均勻分佈,而事實上tt表的情況並非如此。幸而,我們可以很容易地讓MySQL知

道這一點:
shell > myisamchk –analyze PATH_TO_MYSQL_DATABASE/tt
shell > mysqladmin refresh

  
現在這個連接操作已經非常理想,EXPLAIN分析的結果如下:
table type possible_keys key key_len ref rows Extra
tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used
et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1

  
▲ OPTIMIZE

OPTIMIZE能夠恢復和整理磁盤空間以及數據碎片,一旦對包含變長行的表進行了大量的更新或者刪除,進行這個操作就非常有必要了。

OPTIMIZE當前只能用於MyISAM和BDB表。

結束語:從編譯數據庫服務器開始、貫穿整個管理過程,能夠改善MySQL性能的因素實在非常多,本文只涉及了其中很小的一部分。儘管如此

,我們希望本文討論的內容能夠對你有所幫助。

 
//copy者註:
  時間不夠,所以格式上有點問題~~,請大家看詳細的英文原文:http://www.devshed.com/Server_Side/MySQL/Optimize/
或者看看chinabyte的文章好了:
http://www.chinabyte.com/builder/detail.shtm?buiid=1012&parid=1

哈哈~從這點能不能看出來我是全心全意為大家服務的

  • Share/Bookmark

如何改善MySQL數據裝載操作效率的方法

多時候關心的是優化SELECT查詢,因為它們是最常用的查詢,而且確定怎樣優化它們並不總是直截了當。相對來說,將數據裝入數據庫是直截了當的。然而,也存在可用來改善數據裝載操作效率的策略,其基本原理如下:

成批裝載較單行裝載更快,因為在裝載每個記錄後,不需要刷新索引高速緩存;可在成批記錄裝入後才刷新。

在表無索引時裝載比索引後裝載更快。如果有索引,不僅必須增加記錄到數據文件,而且還要修改每個索引以反映增加了的新記錄。

較短的SQL語句比較長的SQL語句要快,因為它們涉及服務器方的分析較少,而且還因為將它們通過網絡從客戶機發送到服務器更快。這些因素中有一些似乎微不足道(特別是最後一個因素),但如果要裝載大量的數據,即使是很小的因素也會產生很大的不同結果。我們可以利用上述的一般原理推導出幾個關於如何最快地裝載數據的實際結論:

LOAD DATA(包括其所有形式)比INSERT效率高,因為其成批裝載行。索引刷新較少,並且服務器只需分析和解釋一條語句而不是幾條語句。

LOAD DATA比LOAD DATA LOCAL效率更高。利用LOAD DATA,文件必須定位在服務器上,而且必須具有FILE權限,但服務器可從磁盤直接讀取文件。利用LOAD DATA LOCAL,客戶機讀取文件並將其通過網絡發送給服務器,這樣做很慢。

如果必須使用INSERT,應該利用允許在單個語句中指定多行的形式,例如:

可在語句中指定的行越多越好。這樣會減少所需的語句數目,降低索引刷新量。如果使用mysqldump生成數據庫備份文件,應該使用–extended-insert選項,使轉儲文件包含多行INSERT語句。還可以使用- – opt(優化) ,它啟用–extended-insert選項。反之,應該避免使用mysqldump的–complete-insert選項;此選項會導致INSERT語句為單行,執行時間更長,比不用–complete-insert選項生成的語句需要更多的分析。

使用壓縮了的客戶機/服務器協議以減少網絡數據流量。對於大多數MySQL客戶機,可以用–compress命令行選項來指定。它一般只用於較慢的網絡,因為壓縮需要佔用大量的處理器時間。

讓MySQL插入缺省值;不要在INSERT語句中指定將以任意方式賦予缺省值的列。平均來說,這樣做語句會更短,能減少通過網絡傳送給服務器的字符數。此外,語句包含的值較少,服務器所進行的分析和轉換就會較少。

如果表是索引的,則可利用批量插入( LOAD DATA或多行的INSERT語句)來減少索引的開銷。這樣會最小化索引更新的影響,因為索引只需要在所有行處理過時才進行刷新,而不是在每行處理後就刷新。

如果需要將大量數據裝入一個新表,應該創建該表且在未索引時裝載,裝載數據後才創建索引,這樣做較快。一次創建索引(而不是每行修改一次索引)較快。

如果在裝載之前刪除或禁用索引,裝入數據後再重新創建或啟用索引可能使裝載更快。如果想對數據裝載使用刪除或禁用策略,一定要做一些實驗,看這樣做是否值得(如果將少量數據裝入一個大表中,重建和索引所花費的時間可能比裝載數據的時間還要長)。

可用DROP INDEX和CREATE INDEX來刪除和重建索引。另一種可供選擇的方法是利用myisamchk或isamchk禁用和啟用索引。這需要在MySQL服務器主機上有一個帳戶,並對錶文件有寫入權。為了禁用表索引,可進入相應的數據庫目錄,執行下列命令之一: 

 

對具有.MYI擴展名的索引文件的MyISAM表使用myisamchk,對具有.ISM擴展名的索引文件的ISAM表使用isamchk。在向表中裝入數據後,按如下激活索引:

如果決定使用索引禁用和激活,應該使用第13章中介紹的表修復鎖定協議以阻止服務器同時更改鎖(雖然此時不對錶進行修復,但要對它像表修復過程一樣進行修改,因此需要使用相同的鎖定協議)。

上述數據裝載原理也適用於與需要執行不同操作的客戶機有關的固定查詢。例如,一般希望避免在頻繁更新的表上長時間運行SELECT查詢。長時間運行SELECT查詢會產生大量爭用,並降低寫入程序的性能。一種可能的解決方法為,如果執行寫入的主要是INSERT操作,那麼先將記錄存入一個臨時表,然後定期地將這些記錄加入主表中。如果需要立即訪問新記錄,這不是一個可行的方法。但只要能在一個較短的時間內不訪問它們,就可以使用這個方法。使用臨時表有兩個方面的好處。首先,它減少了與主表上SELECT查詢語句的爭用,因此,執行更快。其次,從臨時表將記錄裝入主表的總時間較分別裝載記錄的總時間少;相應的索引高速緩存只需在每個批量裝載結束時進行刷新,而不是在每行裝載後刷新。這個策略的一個應用是進入Web服務器的Web頁訪問MySQL數據庫。在此情形下,可能沒有保證記錄立即進入主表的較高權限。

如果數據並不完全是那種在系統非正常關閉事件中插入的單個記錄,那麼減少索引刷新的另一策略是使用MyISAM表的DELAYED_KEY_WRITE表創建選項(如果將MySQL用於某些數據錄入工作時可能會出現這種情況)。此選項使索引高速緩存只偶爾刷新,而不是在每次插入後都要刷新。

如果希望在服務器範圍內利用延遲索引刷新,只要利用–delayed-key-write選項啟動mysqld即可。在此情形下,索引塊寫操作延遲到必須刷新塊以便為其他索引值騰出空間為止,或延遲到執行了一個flush-tables命令後,或延遲到該索引表關閉。

  • Share/Bookmark

MySQL備份、恢復數據庫命令

一直都用phpMyAdmin對MySQL進行管理,簡單方便,近期遇到個奇怪問題:
兩台服務器數據移植,分別是MySQL4.0.26與MySQL5.0.51b,使用phpMyAdmin2.11.7對數據庫進行備份恢復,總是遇到編碼問題,恢復途中錯誤,無法繼續。

兩台機器各自的PHP MySQL與MySQL server版本又都不同,最後只好直接用MySQL命令進行操作,兩句命令,非常簡單:

1、導出一個數據庫

在MySQL的bin目錄執行命令

mysqldump -u用戶名-p密碼數據庫名>導出的文件名

C:\mysql\bin>mysqldump -uroot -p12345678 DB_eliuzd.com > D:\eliuzd2008-6-28.sql

2、只導出數據庫中的一個表

同上,在數據庫名後加表名

mysqldump -u用戶名-p密碼數據庫名表名>導出的文件名

3、導入一個數據庫

先進入MySQL控制台

mysql -u用戶名-p密碼

C:\mysql\bin>mysql -uroot -p12345678

再進入要導入的數據庫

mysql> use數據庫

mysql> use DB_eliuzd.com

最後使用source命令,進行.sql文件的數據導入

mysql> source導入的文件名

mysql> source D:\eliuzd2008-6-28.sql

  • Share/Bookmark