爆肝,52條SQL語句,性能優化,乾貨必收藏 !

SQL語句性能優化html

1, 對查詢進行優化,應儘可能避免全表掃描,首先應考慮在 where 及 order by 涉及的列上創建索引。mysql

2,應儘可能避免在 where 子句中對字段進行 null 值判斷,建立表時NULL是默認值,但大多數時候應該使用NOT NULL,或者使用一個特殊的值,如0,-1做爲默 認值。sql

3,應儘可能避免在 where 子句中使用!=或<>操做符, MySQL只有對如下操做符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些時候的LIKE。數據庫

4,應儘可能避免在 where 子句中使用 or 來鏈接條件, 不然將致使引擎放棄使用索引而進行全表掃描, 能夠 使用UNION合併查詢:select id from t where num=10 union all select id from t where num=20緩存

5,in 和 not in 也要慎用,不然會致使全表掃描,對於連續的數值,能用 between 就不要用 in 了:Select id from t where num between 1 and 3性能優化

6,下面的查詢也將致使全表掃描:select id from t where name like ‘%abc%’ 或者select id from t where name like ‘%abc’若要提升效率,能夠考慮全文檢索。而select id from t where name like ‘abc%’ 纔用到索引服務器

7, 若是在 where 子句中使用參數,也會致使全表掃描。網絡

8,應儘可能避免在 where 子句中對字段進行表達式操做,應儘可能避免在where子句中對字段進行函數操做併發

9,不少時候用 exists 代替 in 是一個好的選擇:select num from a where num in(select num from b).用下面的語句替換:select num from a where exists(select 1 from b where num=a.num)oracle

10,索引當然能夠提升相應的 select 的效率,但同時也下降了 insert 及 update 的效率,由於 insert 或 update 時有可能會重建索引,因此怎樣建索引須要慎重考慮,視具體狀況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

11,應儘量的避免更新 clustered 索引數據列, 由於 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將致使整個表記錄的順序的調整,會耗費至關大的資源。若應用系統須要頻繁更新 clustered 索引數據列,那麼須要考慮是否應將該索引建爲 clustered 索引。

12,儘可能使用數字型字段,若只含數值信息的字段儘可能不要設計爲字符型,這會下降查詢和鏈接的性能,並會增長存儲開銷。

13,儘量的使用 varchar/nvarchar 代替 char/nchar , 由於首先變長字段存儲空間小,能夠節省存儲空間,其次對於查詢來講,在一個相對較小的字段內搜索效率顯然要高些。

14,最好不要使用」「返回全部:select from t ,用具體的字段列表代替「*」,不要返回用不到的任何字段。

15,儘可能避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

16,使用表的別名(Alias):當在SQL語句中鏈接多個表時,請使用表的別名並把別名前綴於每一個Column上.這樣一來,就能夠減小解析的時間並減小那些由Column歧義引發的語法錯誤。

17,使用「臨時表」暫存中間結果

簡化SQL語句的重要方法就是採用臨時表暫存中間結果,可是,臨時表的好處遠遠不止這些,將臨時結果暫存在臨時表,後面的查詢就在tempdb中了,這能夠避免程序中屢次掃描主表,也大大減小了程序執行中「共享鎖」阻塞「更新鎖」,減小了阻塞,提升了併發性能。

18,一些SQL查詢語句應加上nolock,讀、寫是會相互阻塞的,爲了提升併發性能,對於一些查詢,能夠加上nolock,這樣讀的時候能夠容許寫,但缺點是可能讀到未提交的髒數據。使用 nolock有3條原則。查詢的結果用於「插、刪、改」的不能加nolock !查詢的表屬於頻繁發生頁分裂的,慎用nolock !使用臨時表同樣能夠保存「數據前影」,起到相似Oracle的undo表空間的功能,能採用臨時表提升併發性能的,不要用nolock 。

19,常見的簡化規則以下:不要有超過5個以上的錶鏈接(JOIN),考慮使用臨時表或表變量存放中間結果。少用子查詢,視圖嵌套不要過深,通常視圖嵌套不要超過2個爲宜。

20,將須要查詢的結果預先計算好放在表中,查詢的時候再Select。這在SQL7.0之前是最重要的手段。例如醫院的住院費計算。

21,用OR的字句能夠分解成多個查詢,而且經過UNION 鏈接多個查詢。他們的速度只同是否使用索引有關,若是查詢須要用到聯合索引,用UNION all執行的效率更高.多個OR的字句沒有用到索引,改寫成UNION的形式再試圖與索引匹配。一個關鍵的問題是否用到索引。

22,在IN後面值的列表中,將出現最頻繁的值放在最前面,出現得最少的放在最後面,減小判斷的次數。

23,儘可能將數據的處理工做放在服務器上,減小網絡的開銷,如使用存儲過程。存儲過程是編譯好、優化過、而且被組織到一個執行規劃裏、且存儲在數據庫中的SQL語句,是控制流語言的集合,速度固然快。反覆執行的動態SQL,可使用臨時存儲過程,該過程(臨時表)被放在Tempdb中。

24,當服務器的內存夠多時,配製線程數量 = 最大鏈接數+5,這樣能發揮最大的效率;不然使用 配製線程數量<最大鏈接數啓用SQL SERVER的線程池來解決,若是仍是數量 = 最大鏈接數+5,嚴重的損害服務器的性能。

25,查詢的關聯同寫的順序

select a.personMemberID, * from chineseresume a,personmember b where personMemberID = b.referenceid and a.personMemberID = ‘JCNPRH39681’ (A = B ,B = ‘號碼’)

select a.personMemberID, * from chineseresume a,personmember b where a.personMemberID = b.referenceid and a.personMemberID = ‘JCNPRH39681’ and b.referenceid = ‘JCNPRH39681’ (A = B ,B = ‘號碼’, A = ‘號碼’)

select a.personMemberID, * from chineseresume a,personmember b where b.referenceid = ‘JCNPRH39681’ and a.personMemberID = ‘JCNPRH39681’ (B = ‘號碼’, A = ‘號碼’)

26,儘可能使用exists代替select count(1)來判斷是否存在記錄,count函數只有在統計表中全部行數時使用,並且count(1)比count(*)更有效率。

27,儘可能使用「>=」,不要使用「>」。

28,索引的使用規範:索引的建立要與應用結合考慮,建議大的OLTP表不要超過6個索引;儘量的使用索引字段做爲查詢條件,尤爲是聚簇索引,必要時能夠經過index index_name來強制指定索引;避免對大表查詢時進行table scan,必要時考慮新建索引;在使用索引字段做爲條件時,若是該索引是聯合索引,那麼必須使用到該索引中的第一個字段做爲條件時才能保證系統使用該索引,不然該索引將不會被使用;要注意索引的維護,週期性重建索引,從新編譯存儲過程。

29,下列SQL條件語句中的列都建有恰當的索引,但執行速度卻很是慢:

SELECT * FROM record WHERE substrINg(card_no,1,4)=’5378’ (13秒)

SELECT * FROM record WHERE amount/30< 1000 (11秒)

SELECT * FROM record WHERE convert(char(10),date,112)=’19991201’ (10秒)

分析:

WHERE子句中對列的任何操做結果都是在SQL運行時逐列計算獲得的,所以它不得不進行表搜索,而沒有使用該列上面的索引;若是這些結果在查詢編譯時就能獲得,那麼就能夠被SQL優化器優化,使用索引,避免表搜索,所以將SQL重寫成下面這樣:

SELECT * FROM record WHERE card_no like ‘5378%’ (< 1秒)

SELECT * FROM record WHERE amount< 1000*30 (< 1秒)

SELECT * FROM record WHERE date= ‘1999/12/01’ (< 1秒)

30,當有一批處理的插入或更新時,用批量插入或批量更新,毫不會一條條記錄的去更新!

31,在全部的存儲過程當中,可以用SQL語句的,我毫不會用循環去實現!

(例如:列出上個月的每一天,我會用connect by去遞歸查詢一下,毫不會去用循環從上個月第一天到最後一天)

32,選擇最有效率的表名順序(只在基於規則的優化器中有效):

oracle 的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最後的表(基礎表 driving table)將被最早處理,在FROM子句中包含多個表的狀況下,你必須選擇記錄條數最少的表做爲基礎表。若是有3個以上的錶鏈接查詢, 那就須要選擇交叉表(intersection table)做爲基礎表, 交叉表是指那個被其餘表所引用的表.

33,提升GROUP BY語句的效率, 能夠經過將不須要的記錄在GROUP BY 以前過濾掉.下面兩個查詢返回相同結果,但第二個明顯就快了許多.

低效:

SELECT JOB , AVG(SAL)

FROM EMP

GROUP BY JOB

HAVING JOB =’PRESIDENT’

OR JOB =’MANAGER’

高效:

SELECT JOB , AVG(SAL)

FROM EMP

WHERE JOB =’PRESIDENT’

OR JOB =’MANAGER’

GROUP BY JOB

34,sql語句用大寫,由於oracle 老是先解析sql語句,把小寫的字母轉換成大寫的再執行。

35,別名的使用,別名是大型數據庫的應用技巧,就是表名、列名在查詢中以一個字母爲別名,查詢速度要比建鏈接錶快1.5倍。

36,避免死鎖,在你的存儲過程和觸發器中訪問同一個表時老是以相同的順序;事務應經可能地縮短,在一個事務中應儘量減小涉及到的數據量;永遠不要在事務中等待用戶輸入。

37,避免使用臨時表,除非卻有須要,不然應儘可能避免使用臨時表,相反,可使用表變量代替;大多數時候(99%),表變量駐紮在內存中,所以速度比臨時表更快,臨時表駐紮在TempDb數據庫中,所以臨時表上的操做須要跨數據庫通訊,速度天然慢。

38,最好不要使用觸發器,觸發一個觸發器,執行一個觸發器事件自己就是一個耗費資源的過程;若是可以使用約束實現的,儘可能不要使用觸發器;不要爲不一樣的觸發事件(Insert,Update和Delete)使用相同的觸發器;不要在觸發器中使用事務型代碼。

39,索引建立規則:

表的主鍵、外鍵必須有索引;

數據量超過300的表應該有索引;

常常與其餘表進行鏈接的表,在鏈接字段上應該創建索引;

常常出如今Where子句中的字段,特別是大表的字段,應該創建索引;

索引應該建在選擇性高的字段上;

索引應該建在小字段上,對於大的文本字段甚至超長字段,不要建索引;

複合索引的創建須要進行仔細分析,儘可能考慮用單字段索引代替;

正確選擇複合索引中的主列字段,通常是選擇性較好的字段;

複合索引的幾個字段是否常常同時以AND方式出如今Where子句中?單字段查詢是否極少甚至沒有?若是是,則能夠創建複合索引;不然考慮單字段索引;

若是複合索引中包含的字段常常單獨出如今Where子句中,則分解爲多個單字段索引;

若是複合索引所包含的字段超過3個,那麼仔細考慮其必要性,考慮減小複合的字段;

若是既有單字段索引,又有這幾個字段上的複合索引,通常能夠刪除複合索引;

頻繁進行數據操做的表,不要創建太多的索引;

刪除無用的索引,避免對執行計劃形成負面影響;

表上創建的每一個索引都會增長存儲開銷,索引對於插入、刪除、更新操做也會增長處理上的開銷。另外,過多的複合索引,在有單字段索引的狀況下,通常都是沒有存在價值的;相反,還會下降數據增長刪除時的性能,特別是對頻繁更新的表來講,負面影響更大。

儘可能不要對數據庫中某個含有大量重複的值的字段創建索引。

40,mysql查詢優化總結:使用慢查詢日誌去發現慢查詢,使用執行計劃去判斷查詢是否正常運行,老是去測試你的查詢看看是否他們運行在最佳狀態下。長此以往性能總會變化,避免在整個表上使用count(*),它可能鎖住整張表,使查詢保持一致以便後續類似的查詢可使用查詢緩存

,在適當的情形下使用GROUP BY而不是DISTINCT,在WHERE, GROUP BY和ORDER BY子句中使用有索引的列,保持索引簡單,不在多個索引中包含同一個列,有時候MySQL會使用錯誤的索引,對於這種狀況使用USE INDEX,檢查使用SQL_MODE=STRICT的問題,對於記錄數小於5的索引字段,在UNION的時候使用LIMIT不是是用OR。

爲了 避免在更新前SELECT,使用INSERT ON DUPLICATE KEY或者INSERT IGNORE ,不要用UPDATE去實現,不要使用 MAX,使用索引字段和ORDER BY子句,LIMIT M,N實際上能夠減緩查詢在某些狀況下,有節制地使用,在WHERE子句中使用UNION代替子查詢,在從新啓動的MySQL,記得來溫暖你的數據庫,以確保您的數據在內存和查詢速度快,考慮持久鏈接,而不是多個鏈接,以減小開銷,基準查詢,包括使用服務器上的負載,有時一個簡單的查詢能夠影響其餘查詢,當負載增長您的服務器上,使用SHOW PROCESSLIST查看慢的和有問題的查詢,在開發環境中產生的鏡像數據中 測試的全部可疑的查詢。

41,MySQL 備份過程:

從二級複製服務器上進行備份。在進行備份期間中止複製,以免在數據依賴和外鍵約束上出現不一致。完全中止MySQL,從數據庫文件進行備份。

若是使用 MySQL dump進行備份,請同時備份二進制日誌文件 – 確保複製沒有中斷。不要信任LVM 快照,這極可能產生數據不一致,未來會給你帶來麻煩。爲了更容易進行單表恢復,以表爲單位導出數據 – 若是數據是與其餘表隔離的。

當使用mysqldump時請使用 –opt。在備份以前檢查和優化表。爲了更快的進行導入,在導入時臨時禁用外鍵約束。

爲了更快的進行導入,在導入時臨時禁用惟一性檢測。在每一次備份後計算數據庫,表以及索引的尺寸,以便更夠監控數據尺寸的增加。

經過自動調度腳本監控複製實例的錯誤和延遲。按期執行備份。

42,查詢緩衝並不自動處理空格,所以,在寫SQL語句時,應儘可能減小空格的使用,尤爲是在SQL首和尾的空格(由於,查詢緩衝並不自動截取首尾空格)。

43,member用mid作標準進行分表方便查詢麼?通常的業務需求中基本上都是以username爲查詢依據,正常應當是username作hash取模來分表吧。分表的話 mysql 的partition功能就是幹這個的,對代碼是透明的;

在代碼層面去實現貌似是不合理的。

44,咱們應該爲數據庫裏的每張表都設置一個ID作爲其主鍵,並且最好的是一個INT型的(推薦使用UNSIGNED),並設置上自動增長的AUTO_INCREMENT標誌。

45,在全部的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。

無需在執行存儲過程和觸發器的每一個語句後向客戶端發送 DONE_IN_PROC 消息。

46,MySQL查詢能夠啓用高速查詢緩存。這是提升數據庫性能的有效Mysql優化方法之一。當同一個查詢被執行屢次時,從緩存中提取數據和直接從數據庫中返回數據快不少。

47,EXPLAIN SELECT 查詢用來跟蹤查看效果

使用 EXPLAIN 關鍵字可讓你知道MySQL是如何處理你的SQL語句的。這能夠幫你分析你的查詢語句或是表結構的性能瓶頸。EXPLAIN 的查詢結果還會告訴你你的索引主鍵被如何利用的,你的數據表是如何被搜索和排序的……等等,等等。

48,當只要一行數據時使用 LIMIT 1

當你查詢表的有些時候,你已經知道結果只會有一條結果,但由於你可能須要去fetch遊標,或是你也許會去檢查返回的記錄數。在這種狀況下,加上 LIMIT 1 能夠增長性能。這樣同樣,MySQL數據庫引擎會在找到一條數據後中止搜索,而不是繼續日後查少下一條符合記錄的數據。

49,選擇表合適存儲引擎:

myisam: 應用時以讀和插入操做爲主,只有少許的更新和刪除,而且對事務的完整性,併發性要求不是很高的。

Innodb:事務處理,以及併發條件下要求數據的一致性。除了插入和查詢外,包括不少的更新和刪除。(Innodb有效地下降刪除和更新致使的鎖定)。對於支持事務的InnoDB類型的表來講,影響速度的主要緣由是AUTOCOMMIT默認設置是打開的,並且程序沒有顯式調用BEGIN 開始事務,致使每插入一條都自動提交,嚴重影響了速度。能夠在執行sql前調用begin,多條sql造成一個事物(即便autocommit打開也能夠),將大大提升性能。

50,優化表的數據類型,選擇合適的數據類型:

原則:更小一般更好,簡單就好,全部字段都得有默認值,儘可能避免null。

例如:數據庫表設計時候更小的佔磁盤空間儘量使用更小的整數類型.(mediumint就比int更合適)

好比時間字段:datetime和timestamp, datetime佔用8個字節,而timestamp佔用4個字節,只用了一半,而timestamp表示的範圍是1970—2037適合作更新時間

MySQL能夠很好的支持大數據量的存取,可是通常說來,數據庫中的表越小,在它上面執行的查詢也就會越快。

所以,在建立表的時候,爲了得到更好的性能,咱們能夠將表中字段的寬度設得儘量小。例如,

在定義郵政編碼這個字段時,若是將其設置爲CHAR(255),顯然給數據庫增長了沒必要要的空間,

甚至使用VARCHAR這種類型也是多餘的,由於CHAR(6)就能夠很好的完成任務了。一樣的,若是能夠的話,

咱們應該使用MEDIUMINT而不是BIGIN來定義整型字段。

應該儘可能把字段設置爲NOT NULL,這樣在未來執行查詢的時候,數據庫不用去比較NULL值。

對於某些文本字段,例如「省份」或者「性別」,咱們能夠將它們定義爲ENUM類型。由於在MySQL中,ENUM類型被看成數值型數據來處理,

而數值型數據被處理起來的速度要比文本類型快得多。這樣,咱們又能夠提升數據庫的性能。

51, 字符串數據類型:char,varchar,text選擇區別

52,任何對列的操做都將致使表掃描,它包括數據庫函數、計算表達式等等,查詢時要儘量將操做移至等號右邊。

做者 | SimpleWu 來源 | cnblogs.com/SimpleWu/p/9929043.html

相關文章
相關標籤/搜索