MySQL 優化常用方法

JaneWorld發表於2019-06-15

1.選取最適用的欄位屬性
表中欄位的寬度設得儘可能小:char的上限為255位元組(固定佔用空間),varchar的上限65535位元組(實際佔用空間),text的上限為65535。char比varchar處理效率高。
儘量把欄位設定為NOT NULL,執行查詢的時候,資料庫不用去比較NULL值。

2.使用連線(JOIN)來代替子查詢(Sub-Queries)
連線(JOIN)之所以更有效率一些,是因為 MySQL不需要在記憶體中建立臨時表來完成這個邏輯上的需要兩個步驟的查詢工作(聯合查詢的條件加索引更快)。

3.使用聯合(UNION)來代替手動建立的臨時表
把需要使用臨時表的兩條或更多的 SELECT 查詢合併的一個查詢中。
SELECT Name, Phone FROM client UNION SELECT Name, BirthDate FROM author  UNION SELECT Name, Supplier FROM product;

4.事務
儘管我們可以使用子查詢(Sub-Queries)、連線(JOIN)和聯合(UNION)來建立各種各樣的查詢,但不是所有的資料庫操作都可以只用一條或少數幾條SQL語句就可以完成的。更多的時候是需要用到一系列的語句來完成某種工作。
作用是:要麼語句塊中每條語句都操作成功,要麼都失敗。換句話說,就是可以保持資料庫中資料的一致性和完整性。事物以BEGIN 關鍵字開始,COMMIT關鍵字結束。在這之間的一條SQL操作失敗,那麼,ROLLBACK命令就可以把資料庫恢復到BEGIN開始之前的狀態。

5.鎖定表
儘管事務是維護資料庫完整性的一個非常好的方法,但卻因為它的獨佔性,有時會影響資料庫的效能,尤其是在很大的應用系統中。由於在事務執行的過程中,資料庫將會被鎖定,因此其它的使用者請求只能暫時等待直到該事務結束。
LOCK TABLE inventory WRITE 
SELECT Quantity FROM inventory 
WHEREItem='book'; 
... 
UPDATE inventory SET Quantity=11 
WHEREItem='book'; 
UNLOCK TABLES 
這裡,我們用一個 SELECT 語句取出初始資料,通過一些計算,用 UPDATE 語句將新值更新到表中。包含有 WRITE 關鍵字的 LOCK TABLE 語句可以保證在 UNLOCK TABLES 命令被執行之前,不會有其它的訪問來對 inventory 進行插入、更新或者刪除的操作。

6、使用外來鍵
鎖定表的方法可以維護資料的完整性,但是它卻不能保證資料的關聯性。這個時候我們就可以使用外來鍵。例如,外來鍵可以保證每一條銷售記錄都指向某一個存在的客戶。在這裡,外來鍵可以把customerinfo 表中的CustomerID對映到salesinfo表中CustomerID,任何一條沒有合法CustomerID的記錄都不會被更新或插入到 salesinfo中。
CREATE TABLE customerinfo 

CustomerID INT NOT NULL , 
PRIMARY KEY ( CustomerID ) 
) TYPE = INNODB; 
CREATE TABLE salesinfo 

SalesID INT NOT NULL, 
CustomerID INT NOT NULL, 
PRIMARY KEY(CustomerID, SalesID), 
FOREIGN KEY (CustomerID) REFERENCES customerinfo 
(CustomerID) ON DELETECASCADE 
) TYPE = INNODB; 
注意例子中的引數“ON DELETE CASCADE”。該引數保證當 customerinfo 表中的一條客戶記錄被刪除的時候,salesinfo 表中所有與該客戶相關的記錄也會被自動刪除。如果要在 MySQL 中使用外來鍵,一定要記住在建立表的時候將表的型別定義為事務安全表 InnoDB型別。該型別不是 MySQL 表的預設型別。定義的方法是在 CREATE TABLE 語句中加上 TYPE=INNODB。

7.使用索引
查詢語句當中包含有MAX(), MIN()和ORDERBY這些命令的時候,效能提高更為明顯。
索引應建立在那些將用於JOIN, WHERE判斷和ORDER BY排序的欄位上。儘量不要對資料庫中某個含有大量重複的值的欄位建立索引。對於一個ENUM型別的欄位來說,出現大量重複值是很有可能的情況,例如 customerinfo中的“province”.. 欄位,在這樣的欄位上建立索引將不會有什麼幫助;相反,還有可能降低資料庫的效能。

普通索引(由關鍵字KEY或INDEX定義的索引)的唯一任務是加快對資料的訪問速度。因此,應該只為那些最經常出現在查詢條件(WHEREcolumn=)或排序條件(ORDERBYcolumn)中的資料列建立索引。

唯一索引的好處:一是簡化了MySQL對這個索引的管理工作,這個索引也因此而變得更有效率;二是MySQL會在有新記錄插入資料表時,自動檢查新記錄的這個欄位的值是否已經在某個記錄的這個欄位裡出現過了;如果是,MySQL將拒絕插入那條新記錄。也就是說,唯一索引可以保證資料記錄的唯一性。在許多場合,建立唯一索引的目的往往不是為了提高訪問速度,而只是為了避免資料出現重複。

8.優化的查詢語句
SELECT FROM order WHERE YEAR(OrderDate)<2001; 
SELECT
FROM order WHERE OrderDate<"2001-01-01";

SELECT FROM inventory WHERE Amount/7<24; 
SELECT
FROM inventory WHERE Amount<24*7;
避免在查詢中讓MySQL進行自動型別轉換,因為轉換過程也會使索引變得不起作用。

9.索引失效情況
like 以%開頭,索引無效;當like字首沒有%,字尾有%時,索引有效。
or語句前後沒有同時使用索引。當or左右查詢欄位只有一個是索引,該索引失效,只有當or左右查詢欄位均為索引時,才會生效。
組合索引,不是使用第一列索引,索引失效。
資料型別出現隱式轉化。如varchar不加單引號的話可能會自動轉換為int型,使索引無效,產生全表掃描。
在索引欄位上使用not,<>,!=。不等於操作符是永遠不會用到索引的,因此對它的處理只會產生全表掃描。 優化方法: key<>0 改為 key>0 or key<0。
當全表掃描速度比索引速度快時,mysql會使用全表掃描,此時索引失效。

應儘量避免在 where子句中使用or,and,in,not in來連線條件,否則將導致引擎放棄使用索引而進行全表掃描,合理使用union all(允許重複的值,請使用 UNION ALL)。

  1. select id from t where num=10 or num=20    
  2. 可以這樣查詢:    
  3. select id from t where num=10    
  4. union all    
  5. select id from t where num=20

10.引擎的選取
MyISAM索引檔案在資料庫中存放的對應表的磁碟檔案有.frm,.MYD,*.MYI結尾的三個檔案:
frm檔案是存放的表結構,表的定義資訊;
MYD檔案是存放著表中的資料;
MYI檔案存放著表的索引資訊;

InnoDB儲存引擎在磁碟中存放的對應的表的磁碟檔案有.frm,.ibd這兩個檔案;
frm檔案是存放表結構,表的定義資訊;
ibd檔案是存放 表中的資料、索引資訊;

詳細出處參考:https://blog.csdn.net/jinxingfeng_cn/artic...

效能方面的優化:
explain執行計劃==>https://blog.csdn.net/yhl_jxy/article/deta...
一、分表的分類(單表記錄條數達到百萬到千萬級別時就要使用分表)
1.縱向分表
文章標題,作者,分類,建立時間等,是變化頻率慢,查詢次數多,而且最好有很好的實時性的資料,我們把它叫做冷資料。
瀏覽量,回覆數等,類似的統計資訊,或者別的變化頻率比較高的資料,我們把它叫做活躍資料。
首先儲存引擎的使用不同,冷資料使用MyIsam 可以有更好的查詢資料。活躍資料,可以使用Innodb ,可以有更好的更新速度。
就是把原來一張表裡的欄位,冷資料的欄位和活躍資料的欄位分別建立2張表來管理。
2.橫向分表
把大的表結構,橫向切割為同樣結構的不同表,如,使用者資訊表,user_1,user_2 等,表結構是完全一樣。

二、慢查詢
show variables like 'slow%';
show global status like 'slow%';

使用 mysqlreport;
正確使用索引:explain 分析查詢語句,組合索引,索引副作用(佔空間、update)
開啟慢查詢日誌、使用慢查詢分析工具 mysqlsla;
索引快取、索引代價(插入更新索引);
表鎖,行鎖,行鎖副作用(update 多時候變慢),在 select 和 update 混合的情況下,行鎖巧妙解決了讀寫互斥的問題;
開啟使用查詢快取;
修改臨時表記憶體空間;
開啟執行緒池;

MySQL Query 語句優化的基本思路和原則

  1. 優化需要優化的 Query;
  2. 定位優化物件的效能瓶頸;
  3. 明確優化目標;
  4. 從 Explaing 入手;
  5. 多使用 Profile;
  6. 永遠用小結果集推動大的結果集;
  7. 儘可能在索引中完成排序;
  8. 只取自己需要的 Columns;
  9. 僅僅使用最有效的過濾條件;
  10. 儘可能避免複雜的 Join 和子查詢。
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章