1. 程式人生 > >MySql 開發設計規範

MySql 開發設計規範

1.杜絕直接 SELECT * 讀取全部欄位

   即使需要所有欄位,減少網路頻寬消耗,能有效利用覆蓋索引,表結構變更對程式基本無影響

2.能確定返回結果只有一條時,使用 limit 1

   在保證資料不會有誤的前提下,能確定結果集數量時,多使用limit,儘快的返回結果。

3.小心隱式型別轉換

   轉換規則

   a.兩個引數至少有一個是 NULL 時,比較的結果也是 NULL,例外是使用 <=> 對兩個 NULL 做比較時會返回 1,這兩種情況       都 不需要做型別轉換   b. 兩個引數都是字串,會按照字串來比較,不做型別轉換

4. 禁止在where

條件列上使用函式

會導致索引失效,如lower(email)f_qq % 4。可放到右邊的常量上計算

返回小結果集不是很大的情況下,可以對返回列使用函式,簡化程式開發

5. 使用like模糊匹配,%不要放首位

會導致索引失效,有這種搜尋需求是,考慮其它方案,如sphinx全文搜尋

6. 涉及到複雜sql時,務必先參考已有索引設計,先explain

    簡單SQL拆分,不以程式碼處理複雜為由。

    比如 OR 條件: f_phone=’10000’ or f_mobile=’10000’,兩個欄位各自有索引,但只能用到其中一個。可以拆分成2sql,      或者union all

    先

explain的好處是可以為了利用索引,增加更多查詢限制條件

7. 使用join時,where條件儘量使用充分利用同一表上的索引

    如 select t1.a,t2.b * from t1,t2 and t1.a=t2.a and t1.b=123 and t2.c= 4 ,如果t1.ct2.c欄位相同,那麼t1上的索引(b,c)就      只用到b了。此時如果把where條件中的t2.c=4改成t1.c=4,那麼可以用到完整的索引

    這種情況可能會在欄位冗餘設計(反正規化)時出現

    正確選取inner joinleft join

8. 少用子查詢,改用join

    小於5.6版本時,子查詢效率很低,不像Oracle那樣先計運算元查詢後外層查詢。5.6版本開始得到優化

9. 考慮使用union all,少使用union,注意考慮去重

    union all不去重,而少了排序操作,速度相對比union要快,如果沒有去重的需求,優先使用union all

    如果UNION結果中有使用limit,在2個子SQL可能有許多返回值的情況下,各自加上limit。如果還有order by,請找DBA

10. IN的內容儘量不超過200

     超過500個值使用批量的方式,否則一次執行會影響資料庫的併發能力,因為單SQL只能且一直佔用單CPU,而且可能導致         主從複製延遲

11. 拒絕大事務

     比如在一個事務裡進行多個select,多個update,如果是高頻事務,會嚴重影響MySQL併發能力,因為事務持有的鎖等資源       只在事務rollback/commit時才能釋放。但同時也要權衡資料寫入的一致性。

12. 避免使用is null, is not null這樣的比較

13. order by .. limit

     這種查詢更多的是通過索引去優化,但order by的欄位有講究,比如主鍵idf_time都是順序遞增,那就可以考慮order by         id  而非 f_time

14.  c1 < a order by c2

     與上面不同的是,order by之前有個範圍查詢,由前面的內容可知,用不到類似(c1,c2)的索引,但是可以利用(c2,c1)索引。       另外還可以改寫成join的方式實現。

15. 分頁優化

      建議使用合理的分頁方式以提高分頁效率,大頁情況下不使用跳躍式分頁假如有類似下面分頁語句:       SELECT FROM table1 ORDER BY ftime DESC LIMIT 10000,10;     這種分頁方式會導致大量的io,因為MySQL使用的是提前讀取策略。     推薦分頁方式:     SELECT FROM table1 WHERE ftime < last_time ORDER BY ftime DESC LIMIT 10     即傳入上一次分頁的界值SELECT id FROM table ORDER BY time LIMIT 1000010) as t2 ON t1.id=t2.id

16. count計數

    1.首先count()count(1)count(col1)是有區別的,count()表示整個結果集有多少條記錄,count(1)表示結果集裡                     以 primary key統計數量,絕大多數情況下count()count(1)效果一樣的,但count(col1)表示的是結果集裡 col1 NOT           null 的記錄數。優先採用count()

     2.大資料量count是消耗資源的操作,甚至會拖慢整個庫,查詢效能問題無法解決的,應從產品設計上進行重構。例如當頻繁       需要count的查詢,考慮使用匯總表

     3.遇到distinct的情況,group by方式可能效率更高。

17. delete,update語句改成selectexplain

      select最多導致資料庫慢,寫操作才是鎖表的罪魁禍首

18. 減少與資料庫互動的次數,儘量採用批量SQL語句

    1.INSERT ... ON DUPLICATE KEY UPDATE ...,插入行後會導致在一個UNIQUE索引或PRIMARY KEY中出現重複值,則執      行舊行UPDATE,如果不重複則直接插入,影響1行。

    2.REPLACE INTO類似,但它是衝突時刪除舊行。INSERT IGNORE相反,保留舊行,丟棄要插入的新行。

    3.INSERT INTO VALUES(),(),(),合併插入。

19. 杜絕危險SQL

   1.去掉where 1=1 這樣無意義或恆真的條件,如果遇到update/delete或遭到sql注入就恐怖了

   2.SQL中不允許出現DDL語句。一般也不給予create/alter這類許可權,但阿里雲RDS只區分讀寫使用者