很多時候基於php+MySQL建立的網站所出現的系統性能瓶頸往往是出在MySQL上,而MySQL中用的最多的語句就是查詢語句,因此,針對MySQL數據庫查詢語句的優化就顯得至關重要!本文就此問題做出詳細分析如下:
1、判斷是否向MySQL數據庫請求了不需要的數據,如下列情況:
(1)、查詢不需要的數據,例如你需要10條數據,但是你選出了100條數據加了limit做限制。
(2)、多表關聯時返回全部列
(3)、總是取出全部列select*......取出全部列,會讓優化器無法完成索引覆蓋掃描這類優化,還為服務器帶來額外的I/O、內存、和cpu的消耗
(4)、重復查詢相同的數據例如,在用戶評論的地方需要查詢用戶的頭像的URL,那麼用戶多次評論的時候將這個數據緩存起來,需要的時候從緩存取出,這樣性能會更好。
2、mysql是否在掃描額外的記錄
最簡單衡量查詢開銷的三個指標如下:響應時間、掃描的行數、返回的行數
響應時間:服務時間和排隊時間。服務時間是指數據庫處理這個查詢真正花費的時間。排隊時間是指服務器因為等待某些資源而沒有真正執行的查詢。
掃描的行數和返回的行數:理想情況下掃描的行數和返回的行數應該是相同的。
一般MYSQL能夠使用如下三種方式應用where條件記錄,從好到壞依次為:
(1)、在索引中使用where條件來過濾不匹配的記錄,在存儲索引層完成。
(2)、使用索引覆蓋掃描來返回記錄,直接從索引中過濾不需要的記錄並返回命中的結果,在mysql服務器層完成,但無需在回表查詢記錄。
(3)、從數據表中返回數據,然後過濾不滿足條件的記錄,在mysql服務器層完成,需要先從數據表讀出記錄然後過濾
如果發現查詢需要掃描大量的數據但返回少數的行,那麼通常可以嘗試下面的技巧:
(1)、使用索引覆蓋掃描,把所有需要的列都放到索引中,這樣存儲引擎無須返回表獲取對應行就可以返回結果了。
(2)、改變庫表結構,使用單獨的匯總表。
(3)、重寫這個復雜的查詢
3、重構查詢的方式
(1)、一個復雜查詢還是多個簡單查詢:
Mysql內部每秒能夠掃描內存中上百萬條數據,相比之下,mysql響應數據給客戶端就慢得多,在其他條件都相同的時候,使用盡可能少的查詢當然是好的,但有時候將一個大查詢分解為多個小查詢都是很有必要的。
(2)、切分查詢:
刪除舊數據是一個很好的例子,在定期清除大量數據時,如果用一個大的語句一次性完成的話,則可能一次鎖住很多數據,占滿整個事物日志。耗盡系統資源,阻塞很多小的但很重要的查詢。
Mysql>deletefrommessageswherecreated<DATE_SUB(NOW(),INTERVAL3MONTH);
改寫:
Rows_affected=0; Do{ Rows_affected=do_query( “deletefrommessageswherecreated<DATE_SUB(NOW(),INTERVAL3MONTH)”; ) }
(3)、分解關聯查詢:
可以讓緩存的效率更高,在應用程序中可以方便的緩存單條數據
就查詢分解後,執行單個查詢可以減少鎖的競爭
在應用層做關聯,可以更容易對數據庫進行拆分,更容易做到高性能和高擴展
查詢本身效率也會更高。
可以減少冗余數據的查詢,在應用層做關聯查詢,意味著對於某條數據應用只需要查詢一次,而在數據庫中做查詢,可能需要重復的訪問一部分數據。
適合場景:
①當應用程序能夠方便的緩存單個查詢結果的時候;
②當可以將數據分布到不同的mysql服務器上的時候;
③當能夠使用IN()的方式代替關聯查詢的時候;
④當查詢中使用一個數據表的時候。
提高查詢速度:
1.、編寫sql語句時,如果你不是需要所有的列,盡量不要使用select * from,寫上你需要查詢的列。
2、編寫sql時,盡量用where字句過濾掉一部分記錄。
數據庫中某個字段添加了索引後,索引的建立,維護和使用都是有數據庫自己操作的,在SQL語句中不用關注。
關於查詢語句優化,你可以看看danish shasha寫的一本《數據庫系統性能調優》,裡面介紹的一些語句的優化方法 。對於你的語句,裡面的 建議 是 將這個語句變為 兩個 子查詢結果的UNION,即:
select p.id from project p,comment c where c.target_id=p.id and c.target_type=500 and c.uid=10001
Union
select p.id from project p,bookmark b where b.project_id=p.id and b.uid=10001;
仔細看 你 會發現,你原來的語句有不必要的笛卡爾集連接操作,所以慢,因為第一個子查詢和bookmark無關,第二各子查詢和comment無關,但按照你的語句,數據庫生成執行計劃的時候 or的兩個條件都要執行笛卡爾集的運算,會造成很大的開銷的。