mysql性能優化之數據庫級別優化--優化sql語句

一  優化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, ... ;

相關文章
相關標籤/搜索