不少時候,咱們的程序出現的「性能問題」,實際上是咱們本身寫的那"坨"代碼的問題,是本身Coding的問題,是Mysql的DML語句使用的問題。 如下是我總結的關於MySQL DML語句的使用中須要注意的點。mysql
select *
要時刻保持謹慎的態度絕大多數狀況,是不須要select *
的。一旦使用了這種語句,便會讓優化器沒法完成索引覆蓋掃描這類優化,並且還會增長額外的I/O、內存和CPU的消耗。 固然,使用select *
也並非全是壞處,合理的使用select *
能夠簡化開發,提升相同代碼的複用性。git
有時候會發現某些查詢可能須要讀取幾千行數據,可是僅返回幾條或者不多的結果,可使用如下方式去優化:github
傳統的互聯網系統中,強調網絡鏈接儘可能少,數據層儘量在一次鏈接中完成儘量多的工做,防止創建屢次連接,可是這種想法對於MySQL並不適用,MySQL從設計上讓鏈接和斷開都很輕量,在通常服務器上能夠支持每秒超過10萬的查詢。redis
因此對於有些場景下,能夠將一個大的查詢「分而治之」,切分紅小查詢,而後再組合起來。例如如下狀況:sql
一次刪一萬條
。若是用一個大的語句一次性完成的話,可能須要一次鎖住大量數據,佔滿大量日誌事務,讓Mysql停在那兒了,爲避免這種狀況發生,最好一次性刪除一萬條左右的數據,而後每次刪完暫停一下子再操做,將服務器上的一次性壓力分散。注意:雖然Mysql創建鏈接十分輕量,可是這不意味着能夠逐條循環中查詢而後再拼接,這樣效率依然是很是慢,並且一般是工做中sql優化的點。數據庫
join
操做這算是一條禁忌吧,不少公司的互聯網產品都杜絕join操做,換成先從一張表中先取出數據id,再從另一張表中使用where in
查詢的兩次單表查詢操做。主要是如下幾點緣由:緩存
假如非用不可,能夠採用如下方式來優化:服務器
ON
或者using
子句中的列上有索引group by
和order by
中的表達式只涉及到一個表中的列。臨時表
MySQL的臨時表示沒有任何索引的,使用臨時表通常都意味着性能比較低,所以在對性能要求比較高的場景中,最好不要使用帶有臨時表的操做:微信
group by
操做。UNION
查詢。order by
操做,例如distinct
函數和order by
一塊兒使用且distinct
和order by
同一個字段。再例如某些狀況下group by
和order by
字段不一樣。具體是否用到臨時表,能夠經過explain
來查看,查看Extra
列的結果,若是出現Using temporary
則須要注意。markdown
count()
函數優化count()
函數有一點須要特別注意:它是不統計值爲NULL的字段的!因此:不能指定查詢結果的某一列,來統計結果行數。即count(xx column)
不太好。
若是想要統計結果集,就使用count(*)
,性能也會很好。
儘可能別使用子查詢,儘量的使用關聯來代替
limit
一般咱們在分頁的時候,一般使用的是limit 50, 10
這種語句。數據少還不錯,可是當數據偏移量很是大的時候,性能就會出現問題,例如select xx,xxx from test_table limit 100000020, 20
。掃描了100000020條數據,才返回20條數據。這個時候咱們能夠用一下兩種方式來優化:
between and
和主鍵索引利用主鍵自增id,咱們若是知道了分頁的上邊界,以上查詢能夠改寫爲: select xxx, xxx from test_table where id between xxxxx and xxxx
。
order by
加limit
,不使用offsetlimit
和offset
的問題,其實就是offset
的問題,它會致使MySQL掃描大量不須要的行而後再拋棄掉。若是使用某個標籤記錄上一次所取數據的位置,那麼下次就能夠直接從書籤位置開始掃描,這樣就能夠避免使用offset
。
例如以上查詢能夠改成:
第一組數據:``select xxx, xxxx from test_table order by id desc limit 20;
這樣就拿到了本次數據和下次數據的分解id值,則下一頁查詢就知道能夠: select xxx, xxx from test_table where id < '上頁id分界值' order by id desc limit 20
explain
如下是mysql執行查詢的整個過程,explain
能夠查看圖中標紅部分,
explain
會展現不少字段和內容,其中的內容每每很差記,使用的時候,能夠查看如下圖解內容: explain圖解
互聯網技術窩
或者加微信共同探討交流: