為查詢最佳化你的查詢
大多數的MySQL伺服器都開啟了查詢快取。這是提高性最有效的方法之一,而且這是由MySQL的資料庫引擎處理的。當有很多相同的查詢被執行了多次的時候,這些查詢結果會被放到一個快取中,這樣,後續的相同的查詢就不用操作表而直接存取快取結果了。
這裡最主要的問題是,對程式設計師來說,這個事情是很容易被忽略的。因為,我們某些查詢語句會讓MySQL不使用快取。請看下面的範例:
// 查询缓存不开启 $r = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()"); // 开启查询缓存 $today = date("Y-m-d"); $r = mysql_query("SELECT username FROM user WHERE signup_date >= '$today'");
上面兩個SQL語句的差異就是 CURDATE() ,MySQL的查詢快取對這個函數不起作用。所以,像 NOW() 和 RAND() 或是其它的諸如此類的SQL函數都不會開啟查詢緩存,因為這些函數的傳回是會不定的易變的。所以,你所需要的就是用一個變數來取代MySQL的函數,從而開啟快取。
學會使用EXPLAIN
使用EXPLAIN關鍵字可以讓你知道MySQL是如何處理你的SQL語句的。
select id, title, cate from news where cate = 1
發現查詢緩慢,然後在cate欄位上增加索引,則會加快查詢
#當只要一行資料時使用LIMIT 1
當你查詢表格的有些時候只需要一筆數據,請使用limit 1。
正確的使用索引
索引不一定就是給主鍵或是唯一的欄位。如果在你的表中,有某個欄位你總要會經常用來做搜尋、拍下、條件,那麼,請為其建立索引吧。
不要ORDER BY RAND()
效率很低的一種隨機查詢。
避免SELECT *
從資料庫裡讀出越多的數據,那麼查詢就會變得越慢。並且,如果你的資料庫伺服器和WEB伺服器是兩台獨立的伺服器的話,這也會增加網路傳輸的負載。必須應該養成一個需要什麼就取什麼的好的習慣。
使用 ENUM 而不是 VARCHAR
ENUM 類型是非常快且緊湊的。在實際上,其保存的是 TINYINT,但其外表上顯示為字串。這樣一來,用這個欄位來做一些選項清單變得相當的完美。
如果你有一個字段,比如“性別”,“國家”,“民族”,“狀態”或“部門”,你知道這些字段的取值是有限而且固定的,那麼,你應該使用ENUM 而不是VARCHAR。
使用 NOT NULL
除非你有一個很特別的原因去使用 NULL 值,你應該總是讓你的欄位保持 NOT NULL。這看起來好像有點爭議,請往下看。
首先,問問自己「Empty」和「NULL」有多大的差別(如果是INT,就是0和NULL)?如果你覺得它們之間沒有什麼差別,那麼你就不要使用NULL。 (你知道嗎?在Oracle 裡,NULL 和Empty 的字串是一樣的!)
不要以為NULL 不需要空間,其需要額外的空間,並且,在你進行比較的時候,你的程序會更複雜。當然,這裡並不是說你就不能使用NULL了,現實情況是很複雜的,還是會有些情況下,你需要使用NULL值。
以下摘自MySQL自己的文件
「NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”
IP位址存成UNSIGNED INT
很多程式設計師都會建立一個VARCHAR(15) 欄位來存放字串形式的IP而不是整形的IP。如果你用整形來存放,只需要4個字節,並且你可以有定長的字段。而且,這會為你帶來查詢上的優勢,尤其是當你需要使用這樣的WHERE條件:IP between ip1 and ip2。
我們必需要使用UNSIGNED INT,因為IP位址會使用整個32位元的無符號整形
##固定長度的表會更快
如果表格中的所有欄位都是「固定長度」的,則整個表格會被認為是「static」 或「fixed-length」。例如,表中沒有以下類型的欄位: VARCHAR,TEXT,BLOB。只要你包括了其中一個這些字段,那麼這個表就不是「固定長度靜態表」了,這樣,MySQL 引擎會用另一種方法來處理。 固定長度的表會提高效能,因為MySQL搜尋得會更快一些,因為這些固定的長度是很容易計算下一個資料的偏移量的,所以讀取的自然也會很快。而如果欄位不是定長的,那麼,每次要找下一條的話,就需要程式找到主鍵。 並且,固定長度的表也更容易被快取和重建。不過,唯一的副作用是,固定長度的字段會浪費一些空間,因為定長的字段無論你用不用,他都是要分配那麼多的空間。垂直分割#
「垂直分割」是一種把資料庫中的表格按列變成幾張表格的方法,這樣可以降低表格的複雜度和欄位的數目,從而達到最佳化的目的。需要注意的是,這些被分出去的字段所形成的表,你不會經常性地去Join他們,不然的話,這樣的性能會比不分割時還要差,而且,會是極數級的下降。
分割大的DELETE 或INSERT 語句
如果在一個線上的網站上去執行一個大的DELETE 或INSERT 查詢,你需要非常小心,要避免你的操作讓你的整個網站停止對應。因為這兩個操作是會鎖表的,表一鎖住了,別的操作都進不來了。
Apache 會有很多的子行程或執行緒。所以,其工作起來相當有效率,而我們的伺服器也不希望有太多的子進程,線程和資料庫鏈接,這是極大的佔伺服器資源的事情,尤其是內存。
如果你把你的表鎖上一段時間,比如30秒鐘,那麼對於一個有很高訪問量的站點來說,這30秒所積累的訪問進程/線程,數據庫鏈接,打開的檔案數,可能不只讓你泊WEB服務Crash,還可能會讓你的整台伺服器馬上掛了。
越小的列會越快
對於大多數的資料庫引擎來說,硬碟操作可能是最重大的瓶頸。所以,把你的資料變得緊湊會對這種情況非常有幫助,因為這減少了對硬碟的存取。
選擇正確的儲存引擎
在 MySQL 中有兩個儲存引擎 MyISAM 和 InnoDB,每個引擎都有優點和缺點。
MyISAM 適合一些需要大量查詢的應用,但其對於有大量寫入操作並不是很好。甚至你只是需要update一個字段,整個表都會被鎖起來,而別的進程,就算是讀進程都無法操作直到讀取操作完成。另外,MyISAM 對於 SELECT COUNT(*) 這類的計算是超快無比的。
InnoDB 的趨勢會是一個非常複雜的儲存引擎,對於一些小的應用,它會比 MyISAM 還要慢。他是它支援「行鎖」 ,於是在寫操作比較多的時候,會更優秀。並且,他也支援更多的高階應用,例如:事務。
以上是MySQL效能優化的一些經驗的詳細內容。更多資訊請關注PHP中文網其他相關文章!