如下內容參考《高性能Mysql》mysql
這個話題基本上整本書都在討論,這裏須要特別提到的是:sql
確保ON或者USING子句中的列上有索引。在建立索引的時候就要考慮到關聯的順序。
當表A和表B用列c關聯的時候,若是優化器的關聯順序是B、A,那麼就不須要在B表的對應列上建上索引。沒有用到的索引只會帶來額外的負擔。通常來講,除非有其餘理由,不然只須要在關聯順序中的第二個表的相應列上建立索引。性能
確保任何的GROUP BY和ORDER BY中的表達式只涉及到一個表中的列,這樣MySQL
纔有可能使用索引來優化這個過程。優化
當升級MySQL的時候須要注意:關聯語法、運算符優先級等其餘可能會發生變化
的地方。由於之前是普通關聯的地方可能會變成笛卡兒積,不一樣類型的關聯可能會生成不一樣的結果code
在系統中須要進行分頁操做的時候,咱們一般會使用LIMIT加上偏移量的辦法實現,同
時加上合適的ORDER BY子句。若是有對應的索引,一般效率會不錯,不然,MySQL需
要作大量的文件排序操做。排序
一個很是常見又使人頭疼的問題就是,在偏移量很是大的時候注」,例如多是LIMIT
1000,20這樣的查詢,這時MySQL須要查詢1 0 020條記錄而後只返回最後20條,前面
10 000條記錄都將被拋棄,這樣的代價很是高。若是全部的頁面被訪問的頻率都相同,
那麼這樣的查詢平均須要訪問半個表的數據。要優化這種查詢,要麼是在頁面中限制分
頁的數量,要麼是優化大偏移量的性能。索引
優化此類分頁查詢的一個最簡單的辦法就是儘量地使用索引覆蓋掃描,而不是查詢所
有的列。而後根據須要作一次關聯操做再返回所需的列。對於偏移量很大的時候,這樣
作的效率會提高很是大。考慮下面的查詢:ip
mysql> SELECT film_id,description FROM sakila.film ORDER BY title LIMIT 50,5;
若是這個表很是大,那麼這個查詢最好改寫成下面的樣子:it
mysql> SELECT film.film_id,Film.description -> FROM sakila.film ->INNER JOIN( -> SELECT film.film_id FROM sakila.film -> ORDER BY title LIMIT 50,5 ->) AS lim USING(film_id);
這裏的「延遲關聯」將大大提高查詢效率,它讓MySQL掃描儘量少的頁面,獲取需
要訪問的記錄後再根據關聯列回原表查詢須要的全部列。這個技術也能夠用於優化關聯
查詢中的LIMIT子句。io
有時候也能夠將LIMIT查詢轉換爲已知位置的查詢,讓MySQL經過範圍掃描得到到對
應的結果。例如,若是在一個位置列上有索引,而且預先計算出了邊界值,上面的查詢
就能夠改寫爲:
mysql> SELECT film_id, description FROM sakila.Film -> WHERE position BETWEEN so AND 54 0RDER BY position;
對數據進行排名的問題也與此相似,但每每還會同時和GROUP BY混合使用。在這種狀況
下一般都須要預先計算並存儲排名信息。
LIMIT和OFFST的問題,實際上是OFFSET的問題.它會致使MySQL掃描大量不須要的
行而後再拋棄掉。若是可使用書籤記錄上次取數據的位置,那麼下次就能夠直接從該
書籤記錄的位置開始掃描,這樣就能夠避免使用OFFSET。例如,若須要按照租借記錄作
翻頁,那麼能夠根據最新一條租借記錄向後追溯,這種作法可行是由於租借記錄的主鍵
是單調增加的。首先使用下面的查詢得到第一組結果:
mysql> SELECT * FROM sakila.rental -> ORDER BY rental id DESC LIMIT 20;
假設上面的查詢返回的是主鍵爲1 6 049到1 6 03 0的租借記錄,那麼下一頁查詢就能夠
從1 6 030這個點開始:
mysql> SELECT * FROM sakila*rental -> WHERE rental id < 16030, -> ORDER BY rental id DESC LIMIT 20;
該技術的好處是不管翻頁到多麼後面,其性能都會很好。其餘優化辦法還包括使用預先計算的彙總表,或者關聯到一個冗餘表,冗餘表只包含主鍵列和須要作排序的數據列。還可使用Sphinx優化一些搜索操做,參考附錄F能夠獲得更多相關信息。