1. 程式人生 > >MYSQL 八大優化方案

MYSQL 八大優化方案

關於資料庫優化,網上有不少資料和方法,但是不少質量參差不齊,有些總結的不夠到位,內容冗雜。
  偶爾發現了這篇文章,總結得很經典,文章流量也很大,所以拿到自己的總結文集中,積累優質文章,提升個人能力,希望對大家今後開發中也有幫助

1、選取最適用的欄位屬性

MySQL可以很好的支援大資料量的存取,但是一般說來,資料庫中的表越小,在它上面執行的查詢也就會越快。因此,在建立表的時候,為了獲得更好的效能,我們可以將表中欄位的寬度設得儘可能小。

例如,在定義郵政編碼這個欄位時,如果將其設定為CHAR(255),顯然給資料庫增加了不必要的空間,甚至使用VARCHAR這種型別也是多餘的,因為CHAR(6)就可以很好的完成任務了。同樣的,如果可以的話,我們應該使用MEDIUMINT而不是BIGIN來定義整型欄位。

另外一個提高效率的方法是在可能的情況下,應該儘量把欄位設定為NOT NULL,這樣在將來執行查詢的時候,資料庫不用去比較NULL值。

對於某些文字欄位,例如“省份”或者“性別”,我們可以將它們定義為ENUM型別。因為在MySQL中,ENUM型別被當作數值型資料來處理,而數值型資料被處理起來的速度要比文字型別快得多。這樣,我們又可以提高資料庫的效能。

2、使用連線(JOIN)來代替子查詢(Sub-Queries)

MySQL從4.1開始支援SQL的子查詢。這個技術可以使用SELECT語句來建立一個單列的查詢結果,然後把這個結果作為過濾條件用在另一個查詢中。例如,我們要將客戶基本資訊表中沒有任何訂單的客戶刪除掉,就可以利用子查詢先從銷售資訊表中將所有發出訂單的客戶ID取出來,然後將結果傳遞給主查詢,如下所示:

DELETE  FROM  customerinfo

WHERE  CustomerID  NOT  in  (SELECT customerid  FROM  salesinfo)

使用子查詢可以一次性的完成很多邏輯上需要多個步驟才能完成的SQL操作,同時也可以避免事務或者表鎖死,並且寫起來也很容易。但是,有些情況下,子查詢可以被更有效率的連線(JOIN)..替代。例如,假設我們要將所有沒有訂單記錄的使用者取出來,可以用下面這個查詢完成:

SELECT  *  FROM  customerinfo

WHERE  customerid  NOT IN (SELECT customerid   FROM   salesinfo)

如果使用連線(JOIN)..來完成這個查詢工作,速度將會快很多。尤其是當salesinfo表中對CustomerID建有索引的話,效能將會更好,查詢如下:

SELECT  *  FROM  customerinfo

LEFT  JOIN  salesinfo  ON   customerinfo.customerid =salesinfo.customerid

WHERE  salesinfo.customerid   IS NULL

連線(JOIN)..之所以更有效率一些,是因為MySQL不需要在記憶體中建立臨時表來完成這個邏輯上的需要兩個步驟的查詢工作。

3、使用聯合(UNION)來代替手動建立的臨時表

MySQL從4.0的版本開始支援union查詢,它可以把需要使用臨時表的兩條或更多的select查詢合併的一個查詢中。在客戶端的查詢會話結束的時候,臨時表會被自動刪除,從而保證資料庫整齊、高效。使用union來建立查詢的時候,我們只需要用UNION作為關鍵字把多個select語句連線起來就可以了,要注意的是所有select語句中的欄位數目要想同。下面的例子就演示了一個使用UNION的查詢。

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開始之前的狀態。

BEGIN;
  INSERT   INTO   salesinfo   SET   customerid=14;
  UPDATE   inventory   SET   quantity =11   WHERE   item='book';
COMMIT;

事務的另一個重要作用是當多個使用者同時使用相同的資料來源時,它可以利用鎖定資料庫的方法來為使用者提供一種安全的訪問方式,這樣可以保證使用者的操作不被其它的使用者所幹擾。

5、鎖定表

儘管事務是維護資料庫完整性的一個非常好的方法,但卻因為它的獨佔性,有時會影響資料庫的效能,尤其是在很大的應用系統中。由於在事務執行的過程中,資料庫將會被鎖定,因此其它的使用者請求只能暫時等待直到該事務結束。如果一個數據庫系統只有少數幾個使用者來使用,事務造成的影響不會成為一個太大的問題;但假設有成千上萬的使用者同時訪問一個數據庫系統,例如訪問一個電子商務網站,就會產生比較嚴重的響應延遲。

其實,有些情況下我們可以通過鎖定表的方法來獲得更好的效能。下面的例子就用鎖定表的方法來完成前面一個例子中事務的功能。

LOCK TABLE inventory WRITE SELECT quantity  FROM   inventory   WHERE Item='book';

...

UPDATE   inventory   SET   Quantity=11   WHERE  Item='book';UNLOCKTABLES

這裡,我們用一個select語句取出初始資料,通過一些計算,用update語句將新值更新到表中。包含有WRITE關鍵字的LOCKTABLE語句可以保證在UNLOCKTABLES命令被執行之前,不會有其它的訪問來對inventory進行插入、更新或者刪除的操作。

6、使用外來鍵

鎖定表的方法可以維護資料的完整性,但是它卻不能保證資料的關聯性。這個時候我們就可以使用外來鍵。

例如,外來鍵可以保證每一條銷售記錄都指向某一個存在的客戶。在這裡,外來鍵可以把customerinfo表中的customerid對映到salesinfo表中customerid,任何一條沒有合法customerid的記錄都不會被更新或插入到salesinfo中。

CREATE  TABLE   customerinfo( customerid   int primary key) engine = innodb;

CREATE  TABLE   salesinfo( salesid int not null,customerid  int not null, primary key(customerid,salesid),foreign key(customerid)  references  customerinfo(customerid) on delete cascade)engine = innodb;

注意例子中的引數“on delete cascade”。該引數保證當customerinfo表中的一條客戶記錄被刪除的時候,salesinfo表中所有與該客戶相關的記錄也會被自動刪除。如果要在MySQL中使用外來鍵,一定要記住在建立表的時候將表的型別定義為事務安全表InnoDB型別。該型別不是MySQL表的預設型別。定義的方法是在CREATE TABLE語句中加上engine=INNODB。如例中所示。

7、使用索引

索引是提高資料庫效能的常用方法,它可以令資料庫伺服器以比沒有索引快得多的速度檢索特定的行,尤其是在查詢語句當中包含有MAX(),MIN()和ORDERBY這些命令的時候,效能提高更為明顯。

那該對哪些欄位建立索引呢?

一般說來,索引應建立在那些將用於JOIN,WHERE判斷和ORDERBY排序的欄位上。儘量不要對資料庫中某個含有大量重複的值的欄位建立索引。對於一個ENUM型別的欄位來說,出現大量重複值是很有可能的情況

例如customerinfo中的“province”..欄位,在這樣的欄位上建立索引將不會有什麼幫助;相反,還有可能降低資料庫的效能。我們在建立表的時候可以同時建立合適的索引,也可以使用ALTERTABLE或CREATEINDEX在以後建立索引。此外,MySQL從版本3.23.23開始支援全文索引和搜尋。全文索引在MySQL中是一個FULLTEXT型別索引,但僅能用於MyISAM型別的表。對於一個大的資料庫,將資料裝載到一個沒有FULLTEXT索引的表中,然後再使用ALTERTABLE或CREATEINDEX建立索引,將是非常快的。但如果將資料裝載到一個已經有FULLTEXT索引的表中,執行過程將會非常慢。

8、優化的查詢語句

絕大多數情況下,使用索引可以提高查詢的速度,但如果SQL語句使用不恰當的話,索引將無法發揮它應有的作用。

下面是應該注意的幾個方面。

a、 首先,最好是在相同型別的欄位間進行比較的操作

在MySQL3.23版之前,這甚至是一個必須的條件。例如不能將一個建有索引的INT欄位和BIGINT欄位進行比較;但是作為特殊的情況,在CHAR型別的欄位和VARCHAR型別欄位的欄位大小相同的時候,可以將它們進行比較。

b、 其次,在建有索引的欄位上儘量不要使用函式進行操作

例如,在一個DATE型別的欄位上使用YEAE()函式時,將會使索引不能發揮應有的作用。所以,下面的兩個查詢雖然返回的結果一樣,但後者要比前者快得多。

c、第三,在搜尋字元型欄位時,我們有時會使用LIKE關鍵字和萬用字元,這種做法雖然簡單,但卻也是以犧牲系統性能為代價的

例如下面的查詢將會比較表中的每一條記錄。


SELECT  *  FROM  books  WHERE  name  like   "MySQL%"

但是如果換用下面的查詢,返回的結果一樣,但速度就要快上很多:


SELECT  *  FROM  books  WHERE  name >=  "MySQL"  and  name  <"MySQM"

最後,應該注意避免在查詢中讓MySQL進行自動型別轉換,因為轉換過程也會使索引變得不起作用。

相關推薦

MYSQL 八大優化方案

關於資料庫優化,網上有不少資料和方法,但是不少質量參差不齊,有些總結的不夠到位,內容冗雜。  偶爾發現了這篇文章,總結得很經典,文章流量也很大,所以拿到自己的總結文集中,積累優質文章,提升個人能力,希望對大家今後開發中也有幫助1、選取最適用的欄位屬性MySQL可以很好的支援大資料量的存取,但是一般說來,資料庫

java面試題之----mysql優化方案

mysql 引擎 它的 易維 range 概述 .com 設置 常用 本文轉載自segmentfault,原文鏈接:https://segmentfault.com/a/1190000006158186。 當MySQL單表記錄數過大時,增刪改查性能都會急劇下降,可以參考以

Oracle/MySQL 資料庫優化方案/方向

上週老闆說要做一個優化資料庫方案,上週沒做,週一的週會被批了一頓,前兩天出了一個草版方案,這裡記錄一下當沒有經驗沒有方向沒人指導的一個DBA如何著手做個數據庫優化方案和具體做法。   大方向: 優化無非就: sql優化 架構優化 硬體效能優化  

Mysql常用優化方案

摘自:http://www.jb51.net/article/18934.htm 1、選取最適用的欄位屬性  MySQL可以很好的支援大資料量的存取,但是一般說來,資料庫中的表越小,在它上面執行的查詢也就會越快。因此,在建立表的時候,為了獲得更好的效能,我們可以將表中欄

mysql 效能優化方案 (轉)

網 上有不少mysql 效能優化方案,不過,mysql的優化同sql server相比,更為麻煩與複雜,同樣的設定,在不同的環境下 ,由於記憶體,訪問量,讀寫頻率,資料差異等等情況,可能會出現不同的結果,因此簡單地根據某個給出方案來配置mysql是行不通的,最好能使用 status資訊對mysql進行具體

mysql量級數據表的分頁優化方案

lec undo ima BE ESS color info mar asc 前言 Limit分頁通用方案 select * from yundou_v3.bill_info limit 100,20; select * from yundou_v3.bill_info

MySQL大表優化方案

基於用戶 保存 優先 完成 優化方案 想要 存儲 addition 精確 MySQL大表優化方案 mysql 168 當MySQL單表記錄數過大時,增刪改查性能都會急劇下降,可以參考以下步驟

mysql 性能優化方案

說明 mysql的優化 innodb buffer reat iat 緩存命中 isam val 這是一篇關於mysql 性能優化的文章。網上有不少mysql 性能優化方案,不過,mysql的優化同sql server相比,更為麻煩,同樣的設置,在不同的環境下 ,由於內存,

MySQL服務器 IO 100%的分析與優化方案

文件 %u mysq 希望 影響 前言 文章 興趣 排查 前言 壓力測試過程中,如果因為資源使用瓶頸等問題引發最直接性能問題是業務交易響應時間偏大,TPS逐漸降低等。而問題定位分析通常情況下,最優先排查的是監控服務器資源利用率,例如先用TOP 或者nmon等查看CPU、內存

乾貨!!!MySQL 大表優化方案(1)

當MySQL單表記錄數過大時,增刪改查效能都會急劇下降,可以參考以下步驟來優化: 單表優化 除非單表資料未來會一直不斷上漲,否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度,一般以整型值為主的表在千萬級以下,字串為主的表在五百萬以下是沒有太大問題

Mysql-索引,優化方案,以及索引失效情況:

宣告一下:下面的優化方案都是基於 “ Mysql-索引-BTree型別 ” 的 一、EXPLAIN 做MySQL優化,我們要善用 EXPLAIN 檢視SQL執行計劃。 下面來個簡單的示例,標註(1,2,3,4,5)我們要重點關注的資料 type列,連線型別。一個好的sql語句至少要達到ran

Mysql優化方案總結

1.建表優化 – 資料庫正規化 第一正規化(1NF):強調的是列的原子性,即列不能夠再分成其他幾列。 第二正規化(2NF):首先是 1NF,另外包含兩部分內容,一是表必須有主鍵;二是沒有包含在主鍵中的列必須完全依賴於主鍵,而不能只依賴於主鍵的一部分。 如電話列可進行拆分—家庭電話

優秀後端架構師必會知識:史上最全MySQL大表優化方案總結

本文原作者“ manong”,原創發表於segmentfault,原文連結:segmentfault.com/a/1190000006158186 1、引言 MySQL作為開源技術的代表作之一,是網際網路得以廣泛流行的重要基礎技術之一。 國外 GitHub、Airbnb、Yelp、

【轉載】mysql 百萬級記錄時查詢優化方案

 1.對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。   2.應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:   select id from t w

怎麼思考設計MySQL優化方案

在進行MySQL的優化之前,必須要了解的就是MySQL的查詢過程,很多查詢優化工作實際上就是遵循一些原則,讓MySQL的優化器能夠按照預想的合理方式執行而已。 圖-MySQL查詢過程 一、優化的哲學 注:優化有風險,涉足需謹慎 1、優化可能帶來的問題 優化不總是對一個單純的環境進行,還

MySQL 大資料量表優化方案

單表優化 除非單表資料未來會一直不斷上漲(例如網路爬蟲),否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度 一般以整型值為主的表在 千萬級以下,字串為主的表在 五百萬以下是沒有太大問題的。而事實上很多時候 MySQL 單表的效能依然有不少優化空間,甚至能正

MySQL資料庫優化——優化方案

  可以從哪幾個方面進行資料庫的優化?如下圖所示: SQL及索引優化 根據需求寫出良好的SQL,並建立有效的索引,實現某一種需求可以多種寫法,這時候我們就要選擇一種效率最高的寫法。這個時候就要了解sql優化 資料庫表結構優化 根據資料庫的正規化

使用噹噹sharding-jdbc分表,Mysql LIMIT分頁的優化方案

通過記錄上次查詢結果的最後一條記錄的ID進行下一頁的查詢: SELECT * FROM t_order WHERE id > 100000 LIMIT 10 因此,衍生出另一個問題,如何獲取上次查詢結果的最後一條記錄的ID? 暫時的SQL寫法有兩種: 1)

mysql 資料庫優化之 django分表方案

由來這個問題戳到了Django ORM的痛點,對於多資料庫/分庫的問題,Django提供了很好的支援,通過using和db router可以很好的完成多資料庫的操作。但是說到分表的問題,就有點不那麼友好了。但也不是那麼難處理,只是處理起來不太優雅。解析在Django中,資料庫

MySQL 大表優化方案(長文)

當MySQL單表記錄數過大時,增刪改查效能都會急劇下降,可以參考以下步驟來優化:單表優化除非單表資料未來會一直不斷上漲,否則不要一開始就考慮拆分,拆分會帶來邏輯、部署、運維的各種複雜度,一般以整型值為主的表在千萬級以下,字串為主的表在五百萬以下是沒有太大問題的。而事實上很多時候MySQL單表的效能依然有不少優