天天看點

MySQL 資料庫規範--開發篇

目錄

1.sql語句編寫

2.explain 工具的使用--重點

SQL編寫

1.執行大的delete、update、insert操作要慎重,特别是對業務繁忙的系統,要盡量避免對線上業務産生影響。
  解決辦法是:大操作切割為小操作,使用limit子句限制每次操作的記錄數,也可以利用一些日期字段基于更小粒度的時間範圍進行操作。

2.避免使用select * 語句,select語句之用于擷取需要的字段。

3.使用預編譯語句,可以提高性能并且防範 sql注入 攻擊。

4.一般情況下update,delete 語句中不要使用limit。

5.where 條件語句中必須使用合适的類型,避免mysql進行隐式轉換。

6.insert into 必須顯式指明字段名稱,不要使用insert into table()。

7.避免在sql 語句中進行數學運算或函數運算,避免将業務邏輯和資料存儲耦合在一起。

8.insert 語句如果使用批量送出,如insert into table values(),()...那麼values 的個數不應過多。一次性送出過多記錄,會導緻I/O緊張,出現慢查詢。

9.避免使用存儲過程、觸發器、函數等,這些特性會将業務邏輯與資料庫耦合在一起,并且MySQL的存儲過程,觸發器,函數中可能存在bug。

10.盡量避免使用子查詢,連接配接。盡量将子查詢轉化為連接配接查詢,mysql 查詢優化器會優化連接配接查詢,但連接配接的表要盡可能的少,如果很多,可以考慮反範式設計。即對設計階段做一些改造。

11.使用合理的sql語句以減少與資料庫的互動次數。

12.建議使用合理的分頁技術以提高操作效率。
           

2.explain 工具的使用

explain工具的作用

1.使用 explain 工具可以确認執行計劃是否良好,查詢是否走了合理的索引。
2.不同版本MySQL 優化器各有不同,一些優化規則随着版本的發展可能有變化,
  查詢的執行計劃随着資料的變化也可能發生變化,這類情況就需要使用explain 來驗證自己的判斷。
           

explain 工具實操

執行如下腳本,觀察控制台輸出

explain select name from test where id = 32;
           

注意資料表使用如下腳本:

CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8;
           

table name = test、column1 = id、column2 = name.

執行結果如下所示:

MySQL 資料庫規範--開發篇

螢幕快照 2017-03-30 上午10.36.34.png

下面詳細闡述explain 輸出的各項内容:

id:

包含一組數字,表示查詢中執行 select子句 或操作表的順序。

如果 id 相同,則執行順序由上到下。

select_type:

表示查詢中每個 select 子句的類型(是簡單還是複雜)輸出結果類似如下:

1.simple

查詢中不包含子查詢或者union

2.primary

查詢中若包含任何複雜子查詢,最外層查詢被标記為primary

3.subquery

在select 或 where 清單中包含了子查詢,則該查詢被标記為subquery

4.derived

在from清單中包含的子查詢被标記為derived(衍生)

5.union

若第二個select出現在union之後,則被标記為derived。

6.union result

從union表中擷取結果的select将被标記為 union result。

select_type 隻需要了解分類即可,這個資訊并不是最有價值的。

type:最有價值資訊之一

type表示 MySQL 在表中找到所需行的方式,又稱為“通路類型”,常見的類型如下所示:

all、index、range、ref、eq_ref、const,system,null

以上類型,由左至右,由最差到最好。

all: Full Table Scan,MySQL 将周遊全表以找到比對的行。

index:Full Index Scan,index 與 all 差別為index類型隻周遊索引樹。假設表中有主鍵字段id,則select id from table_name;type即為Full Index Scan。

range:索引掃描範圍,對索引的掃描開始于某一點,傳回比對的域或行,常見于between、<、>等的查詢。

ref:非唯一性索引掃描,将傳回比對某個單獨值得所有行。常見于使用非唯一索引或唯一索引的非唯一字首的查找。

eq_ref:唯一性索引掃描,對于每個索引鍵表中隻有一條記錄與之比對。常見于主鍵或唯一索引掃描。

const、system:當MySQL對查詢的某部分進行優化,并轉化為一個常量時,可使用這些類型進行通路。如果主鍵置于where清單中,MySQL就能将該查詢轉換為一個常量,system是const

的一個特例,當查詢的表隻有一行的情況下,即可使用system。

null:MySQL 在優化過程中分解語句,執行時甚至不用通路表或索引,舉例如下:

explain select * from (select * from t1 where id = 1)d1;

possible_keys

possible_keys 将指出MySQL能使用哪個索引在表中找到行,查詢涉及的字段上若存在索引,則該索引将被列出,但不一定會被查詢使用。

key:最有價值資訊之二

key 将顯示MySQL在查詢中實際使用到的索引,若沒有使用索引,則顯示為null。查詢中若使用到了覆寫索引,則該索引僅僅出現在 key 清單中,possible_keys中并不顯示。

key_len

key_len表示索引中使用的位元組數,可通過該列計算查詢中使用的索引的長度。

ref

ref表示上述表的連接配接比對條件,即哪些列或常亮被用于查找索引列上的值。

rows:最有價值資訊之三

rows 表示MySQL根據表統計資訊及索引選用的情況, 估算查找所需記錄需要讀取的行數。使用到索引一般情況下會使得rows的值降低。

Extra:最有價值資訊之四

Extra 包含不适合在其他列中顯示但十分重要的額外資訊。可能包如下4種資訊。

1.Using index

該值表示相應的select操作中使用到了覆寫索引,包含滿足查詢需要的資料的索引稱為覆寫索引。

2.Using where

如果查詢未能使用索引,則Using where 的作用隻是提醒我們 MySQL 将用where 子句來過濾結果集。

3.Using temporary

表示MySQL需要使用臨時表來存儲結果集,常見于order by 與 group by,事實上group by會進行隐式的order by。

如果我們在group by 時利用索引分組(其實包含排序的過程)排序,則可以提高性能,因為不會此時查詢輸出裡沒有了Using temporary,Using filesort。

4.Using filesort

Using filesort 即檔案排序,MySQL 中将無法使用索引完成的排序操作,稱為檔案排序。

上文篇幅有點長,但都是必須了解的概念。最有價值資訊是我們判斷sql語句執行是否高效的基準,了解四個最有價值資訊是最重要的。

繼續示範explain的使用,使用上文的評判标準來看下語句的執行效率:

1.主鍵查詢

MySQL 資料庫規範--開發篇

主鍵查詢

上述為主鍵查詢的explain資訊

type = const 效率很高

key = primary 實際使用的索引為主鍵

rows = 1 查找的記錄數為1

extra = null ,沒有任何額外資訊

總體來說,性能是極高。

2.主鍵範圍查詢

MySQL 資料庫規範--開發篇

主鍵範圍查詢

上述為主鍵範圍查詢的explain資訊

type =range 範圍查詢,效率不是最低

rows = 7 查找的記錄數為7

extra = Using where ,最終使用where 做結果集過濾,未使用到覆寫索引。

總體來說,性能是很高。

3.未帶索引查詢

MySQL 資料庫規範--開發篇

未帶索引查詢

如上圖所示,name 并未做索引。

type =ALL Full Table Scan 全表查詢

key =NULL 未使用索引

rows = 7 10資料庫中所有記錄

總體來說,性能極差。(這也是我司内部deviceId接口出問題的終極原因)。

4.未帶索引的分組查詢

MySQL 資料庫規範--開發篇

未帶索引的分組查詢

extra = Using where ,最終使用where 做結果集過濾,未使用到覆寫索引。并使用到了temporary,filesort 臨時表與檔案查詢。

總體來說,性能極差。

5.帶索引的分組查詢

我們現在為4與3中 name 建立索引,再來看看分析結果

建立索引腳本如下

alter table test add index idx_name(name);

MySQL 資料庫規範--開發篇

name 被索引之後的效果

再運作3 和 4中的查詢語句

結果如下圖所示:

MySQL 資料庫規範--開發篇

非分組帶索引查詢

type =ref 非唯一索引掃描,效率不是最低

key =name 實際使用的索引name索引(注意:idx_name與name都是在name字段上建立的索引)。

extra = Using index ,最終使用到覆寫索引。

總體來說,查詢性能是極高的。

MySQL 資料庫規範--開發篇

索引分組查詢

type =range 範圍掃描,效率不是最低

extra = Using index ,最終使用where 做結果集過濾,使用到覆寫索引。

當然上述示範比較簡單,也不是非常具備實戰色彩,對于explain的使用,我們還應在更多的資料庫操作場景中多多使用,這是sql調優的利器。為我們後期的調優減輕了負擔,可以說如果在這一步做好了sql腳本的設計,那麼後期關于 sql調優 問題會非常少。

部落格搬家:[大坤的個人部落格] http://markfork.com/

)

歡迎評論哦~