一 優化SELECT語句sql
1.1 WHERE子句優化函數
本文暫時只討論能夠處理WHERE子句的優化,下面的一些實例使用SELECT語句,可是相同的優化一樣適用DELETE和UPDATE語句中的WHERE子句,一樣文中有些做者也不理解的地方,但願路過的大神指教優化
你或許會重寫你的查詢來讓計算操做更快,或許會犧牲一些可讀性.你一般能夠不用浪費這個時間,由於MySQL會自動執行相同的優化,
並且會讓查詢更加容易理解,更加容易維護.MySQL會執行以下優化:orm
1 刪除沒必要要的括號排序
((a and b ) and c or (((a and b ) and ( c and d ))))索引
---> (a and b and c ) or (a and b and c and d)隊列
2 恆定摺疊(儘可能使用常量,不使用變量)事務
( a > b and b = c) and a = 5 內存
--> b > 5 and b = c and a = 5form
3 恆定條件去除 (去除無用的sql條件)
( b >=5 and b = 5 ) or ( b = 6 and 5 = 5 ) or ( b = 7 and 5 = 6 )
---> b = 5 or b = 6
4 索引使用的常量表達式僅計算一次 ?
5 COUNT(*)優化
COUNT(*)在沒有WHERE的單個表上時直接從Myisam和MEMORY表的表信息中檢索. 當僅與一個表使用時,這也適用於任何 NOT NULL表達式。
對於諸如Innodb之類的事務型存儲引擎,不會存儲確切的行數,由於可能正在發生多個事務,每一個事務均可能影響計數,
6 儘早檢測無效的常量表達式
MySQL快速檢測到一些select語句是不可能的,而且不返回任何的行。
7 儘可能將WHERE、HAVING合併
若是不使用GROUP BY 或聚合函數 (COUNT() MIN() AVG()等),儘可能將HAVING與WHERE合併
select * from t1 (select * from tab where id > 10) as t2 where t1.age > 10 and t2.age < 25
--> select * from t1,tab as t2 where t1.age > 10 and t2.id > 10 and t2.age < 25.
具體步驟:
1)from與form合併,修改相應的參數
2)where與where合併,用and鏈接
3)修改相應的謂詞(in改=)
8 對於鏈接中的每一個表,構造一個更簡單的WHERE條件,以便快速的對錶的條件進行評估,並儘量快的跳過行。(鏈接的時候 join on 的列要簡單)
9 在查詢任何其餘表以前,首先讀取的是常量表;常量表能夠是下面的任何一種
1) 空的表或只有一行的表
2) 在主鍵或惟一索引上使用where子句的表,其中全部索引部件都與常量表達式比較,並被定義爲 NOT NULL
下面全部表都被用做常量表
select * from t where primary_key = 1;
select * from t1,t2 where t1.primary_key = 1 and t2.primary_key = t1.id;
10 經過嘗試join的全部組合來找到最好的組合方式。若是ORDER BY,GROUP BY 語句裏面全部的列都來自同一個數據表,這個數據表迴應該是join的第一個數據表
11 若是ORDER BY和GROUP BY語句不一樣,或者若是ORDER BY和GROUP BY 包含列來自的數據表和join隊列裏第一個數據表不一樣,一個臨時表將會被建立
12 若是你使用了SQL_SMALL_REDULT選項,MySQL使用內存臨時表
13 每一個數據表的索引都會被查詢,會使用一個最好的索引,除非優化器相信當前選擇直接表掃描更加高效.從前,最佳索引判斷是索引是否可以過濾表的
百分之30的數據.可是固定的百分比將不會是決定使用索引仍是表掃描的因素. 當前的優化器如今更加複雜,基於包含其餘因素的估價模型,好比表的大小,行的數目,
I/O塊數目.
14 在有些樣例下,MySQL可以從索引中直接讀取行而且不用讀取數據文件,若是索引中全部的行都是數字類型,僅使用索引書來解決查詢
15 在每一行輸出前,跳過與HAVING子句不匹配的行
16 優化選擇條件的排列順序, 把可以過濾更多數據的條件放在前面,過濾少的條件放在後面
例如: select * from user
where id = 1 // 條件1 過濾數據較多
and class_id > 1000; // 條件2 過濾數據較少
下面是一些查詢速度較快的示例:
select count(*) from t1;
SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
SELECT MAX(key_part2) FROM tbl_name
WHERE key_part1=constant;
SELECT ... FROM tbl_name
ORDER BY key_part1,key_part2,... LIMIT 10;
SELECT ... FROM tbl_name
ORDER BY key_part1 DESC, key_part2 DESC, ... LIMIT 10;
若是索引列是數字型的,MySQL僅使用二級索引解決如下查詢:
SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
SELECT COUNT(*) FROM tbl_name
WHERE key_part1=val1 AND key_part2=val2;
SELECT key_part2 FROM tbl_name GROUP BY key_part1;
如下查詢使用索引數據按排序順序檢索行,而無需單獨的排序傳遞:
SELECT ... FROM tbl_name
ORDER BY key_part1,key_part2,... ;
SELECT ... FROM tbl_name ORDER BY key_part1 DESC, key_part2 DESC, ... ;