(4)MySQL進階篇SQL優化(經常使用SQL的優化)

1.概述

前面咱們介紹了MySQL中怎麼樣經過索引來優化查詢。平常開發中,除了使用查詢外,咱們還會使用一些其餘的經常使用SQL,好比 INSERT、GROUP BY等。對於這些SQL語句,咱們該怎麼樣進行優化呢?本節將針對這些SQL語句介紹一些優化的方法。數據庫

2.優化INSERT語句

當進行數據INSERT的時候,能夠考慮採用如下幾種優化方式:
若是同時從同一客戶插入不少行,儘可能使用多個值表的INSERT語句,這種方式將大大縮減客戶端與數據庫之間的鏈接、關閉等消耗,使得效率比分開執行的單個INSERT語句快(在一些狀況中幾倍)。下面是一次插入多值的一個例子:性能優化

insert into test values(1,2),(1,3),(1,4)…

若是從不一樣客戶插入不少行,能經過使用INSERT DELAYED語句獲得更高的速度。DELAYED的含義是讓INSERT語句立刻執行,其實數據都被放在內存的隊列中,並無真正寫入磁盤,這比每條語句分別插入要快的多;LOW_PRIORITY恰好相反,在全部其餘用戶對錶的讀寫完後才進行插入;
將索引文件和數據文件分在不一樣的磁盤上存放(利用建表中的選項);
若是進行批量插入,能夠增長bulk_insert_buffer_size變量值的方法來提升速度。可是,這隻能對MyISAM表使用;
當從一個文本文件裝載一個表時,使用LOAD DATA INFILE。這一般比使用不少INSERT語句快20倍。性能

3.優化GROUP BY語句

默認狀況下,MySQL對全部GROUP BY col1,col2....的字段進行排序。這與在查詢中指定ORDER BY col1,col2...相似。所以,若是顯式包括一個包含相同的列的ORDER BY子句,則對MySQL的實際執行性能沒有什麼影響。若是查詢包括GROUP BY,但用戶想要避免排序結果的消耗,則能夠指定ORDER BY NULL禁止排序,以下面的例子:優化

EXPLAIN SELECT StockType,SUM(StockQty) FROM goods_stock GROUP BY StockType;

EXPLAIN SELECT StockType,SUM(StockQty) FROM goods_stock GROUP BY StockType ORDER BY NULL;


從上面的例子能夠看出第一個SQL語句須要進行「filesort」,而第二個SQL因爲ORDER BY NULL不須要進行「filesort」,而filesort每每很是耗費時間。spa

4.優化ORDER BY語句

在某些狀況中,MySQL可使用一個索引來知足ORDER BY子句,而不須要額外的排序。WHERE條件和ORDER BY使用相同的索引,而且ORDER BY的順序和索引順序相同,而且ORDER BY的字段都是升序或者都是降序。例以下列SQL可使用索引:3d

EXPLAIN SELECT * FROM goods_stock WHERE Model='LM358' ORDER BY Model,LotNO;


可是在如下幾種狀況下則不使用索引:code

EXPLAIN SELECT * FROM goods_stock ORDER BY Model DESC,LotNO ASC;

EXPLAIN SELECT * FROM goods_stock WHERE LotNO=2020 ORDER BY Model;

EXPLAIN SELECT * FROM goods_stock ORDER BY Model,LotNO;

5.優化嵌套查詢

MySQL支持SQL的子查詢。可使用SELECT語句來建立一個單列的查詢結果,而後把這個結果做爲過濾條件用在另外一個查詢中。使用子查詢能夠一次性地完成不少邏輯上須要多個步驟才能完成的SQL操做,同時也能夠避免事務或者表鎖死,而且寫起來也很容易。可是,有些狀況下,子查詢能夠被更有效率的鏈接(JOIN)替代。在下面的例子中,要從goods_stock表中找到那些在goods_stock_price表中不存在階梯價格的庫存:blog

EXPLAIN SELECT * FROM goods_stock WHERE StockGUID NOT IN (SELECT StockGUID FROM goods_stock_price);


從上面執行計劃能夠看到goods_stock表是走了全表掃描的,goods_stock、goods_stock_price表查詢結果是在內存上建立臨時表存儲的,若是使用鏈接(JOIN)來完成這個查詢工做,速度將會快不少。尤爲是當goods_stock_price表中對 goods_stock.StockGUID建有索引的話,性能將會更好,具體查詢以下:排序

EXPLAIN SELECT s.* FROM goods_stock AS s LEFT JOIN goods_stock_price AS sp
ON s.StockGUID=sp.StockGUID
WHERE sp.StockGUID IS NOT NULL;


從執行計劃中能夠明顯看出查詢掃描的記錄範圍和使用索引的狀況都有了很大的改善。鏈接(JOIN)之因此更有效率一些,是由於MySQL不須要在內存中建立臨時表來完成這個邏輯上的須要兩個步驟的查詢工做。索引

6.MySQL如何優化OR條件

對於含有OR的查詢子句,若是要利用索引,則OR之間的每一個條件列都必須用到索引;若是沒有索引,則應該考慮增長索引。例如,首先使用show index命令查看goods_stock表的索引,可知它有3個非彙集索引,在StockGUID、LotNO兩個字段上分別有1個獨立的索引,在Model和Brand字段上有1個複合索引。

SHOW INDEX FROM goods_stock;


而後在兩個獨立索引上面作OR操做,具體以下:

EXPLAIN SELECT * FROM goods_stock WHERE LotNO='2020' OR StockGUID='werer-1weq-hdf1-qgqq';


能夠發現查詢正確的用到了索引,而且從執行計劃的描述中能夠發現MySQL在處理含有OR字句的查詢時,實際是對OR的各個字段分別查詢後的結果進行了UNION。可是當在建有複合索引的列Model和Brand上面作OR操做的時候,卻不能用到索引,具體結果以下:

EXPLAIN SELECT * FROM goods_stock WHERE Model='LM358' OR Brand='2020';

7.使用SQL提示

SQL提示(SQL HINT)是優化數據庫的一個重要手段,簡單來講就是在SQL語句中加入一些人爲的提示來達到優化操做的目的。下面是一個使用SQL提示的例子:

SELECT SQL_BUFFER_RESULTS * FROM...

這個語句將強制MySQL生成一個臨時結果集。只要臨時結果集生成後,全部表上的鎖定均被釋放。這能在遇到表鎖定問題時或要花很長時間將結果傳給客戶端時有所幫助,由於能夠儘快釋放鎖資源。下面是一些在MySQL中經常使用的SQL提示。

7.1USE INDEX

在查詢語句中表名的後面,添加USE INDEX來提供但願MySQL去參考的索引列表,就可讓MySQL再也不考慮其餘可用的索引:

EXPLAIN SELECT * FROM goods_stock USE INDEX (idx_stock_3) WHERE LotNO='2020';

7.2IGNORE INDEX

若是用戶只是單純地想讓MySQL忽略一個或者多個索引,則可使用IGNORE INDEX做爲HINT。一樣是上面的例子,此次來看一下查詢過程忽略索引idx_stock_3的狀況:

EXPLAIN SELECT * FROM goods_stock IGNORE INDEX (idx_stock_3) WHERE LotNO='2020';


從執行計劃能夠看出,系統忽略了指定的索引,而使用了全表掃描。

7.3FORCE INDEX

爲強制MySQL使用一個特定的索引,可在查詢中使用FORCE INDEX做爲HINT。例如,當不強制使用索引的時候,由於goods_stock_price.GoodsStockID(已加索引)的值都是大於0的,所以MySQL會默認進行全表掃描,而不使用索引,以下所示:

EXPLAIN SELECT * FROM goods_stock_price WHERE GoodsStockID>0;


可是,當使用FORCE INDEX進行提示時,即使使用索引的效率不是最高,MySQL仍是選擇使用了索引,這是MySQL留給用戶的一個自行選擇執行計劃的權力。加入FORCE INDEX提示後再次執行上面的SQL:

EXPLAIN SELECT * FROM goods_stock_price FORCE INDEX(idx_stock_price_1) WHERE GoodsStockID>0;


果真,執行計劃中使用了FORCE INDEX後的索引。

8.總結

SQL優化問題是數據庫性能優化最基礎也是最重要的一個問題,實踐代表不少數據庫性能問題都是由不合適的SQL語句形成。本章經過實例描述了SQL優化的通常過程,從定位一個有性能問題的SQL語句到分析產生性能問題的緣由,最後到採起什麼措施優化SQL語句的性能。另外還介紹了優化SQL語句常常須要考慮的幾個方面,好比索引、表分析、排序等。參考文獻:深刻淺出MySQL大全

相關文章
相關標籤/搜索