mysql 判斷字段為null表示 false 其它為true_日拱一卒,MySQL數據庫 常用SQL優化技巧 十一式...

38559f8a8b9f12421aec300f0739183f.png

本文中所提到的SQL優化技巧均是基于Mysql 索引 BTree類型 。將從以下幾個方面介紹常用的SQL優化技巧:

  • 避免在 WHERE 子句中使用 !=<> 操作符。
  • 避免在 WHERE 子句中對索引列使用 %前綴模糊查詢
  • 避免在 WHERE 子句中對索引列使用 OR 來連接條件。
  • 避免在 WHERE 子句中對索引列使用 IN NOT IN
  • 避免在 WHERE 子句中對索引列使用計算、函數、類型轉換等操作。
  • 避免在 WHERE 子句中對索引列使用參數
  • 使用合理的分頁方式以提高分頁的效率。
  • 使用 EXISTS 替換 DISTINCT
  • 避免在 WHERE 子句中對索引列進行 NULL 值判斷。
  • 避免在 WHERE 子句中對索引列進行 隱式類型轉換
  • 合理使用 復合索引

本文篇幅較長 ,建議先收藏再閱讀,便于后續查閱。


善用EXPLAIN

通常,我們在寫完較為復雜的 SQL 時,一般會進行一下 MySQL 優化,我們要善用 EXPLAIN 查看 SQL 執行計劃。

Explain語法

e2745f1f0ac1ebf976e2b76e35475bb5.png

如下

bf90f757b1a33a977436990979bcc34d.png

執行計劃包含如下信息:

  • type:連接類型。一般來說,需要保證查詢至少達到 range 級別,最好能達到 ref,杜絕出現 all 級別。
  • key:實際使用的索引,如果沒有可用的索引,則顯示為NULL,可以使用force index強制索引方式。
  • key_len: 索引字段的最大可能長度,理論上長度越短越好,但并非實際使用長度。
  • rows: 表示MySQL根據表統計信息及索引選用情況,估算的找到所需的記錄所需要讀取的行數,ROWS值的大小是個統計抽樣結果,并不十分準確。
  • extra: 額外說明,當出現Using filesort, Using temporary的時候需要注意。

避免在 WHERE 子句中使用 != 或 <> 操作符

應盡量避免在 WHERE 子句中使用 !=<> 操作符,否則將導致引擎放棄使用索引而進行全表掃描。MySQL 只有對以下操作符才會使用索引:,>=,BETWEEN,IN,以及使用 LIKE 時的 后綴模糊查詢 %

a1c4eda00c6eea89a02883eb864cfb19.png

避免在WHERE 子句中對索引列使用 %前綴模糊查詢

WHERE 子句中使用 LIKE進行模糊查詢時,使用 %前綴模糊查詢 無法使用索引,從而引發全表掃描。解決 %前綴模糊查詢時索引不被使用的方法就是添加覆蓋索引(只訪問索引的查詢,索引和查詢列一致,只需掃描索引而無須回表)。

b0241a1405eda8afbcd4c1a2d4fea01d.png

避免在WHERE 子句中對索引列使用 OR 來連接條件

應盡量避免在 WHERE 子句中使用 OR 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描。使用 OR 的字句可以分解成多個查詢,并且通過 UNION 連接多個查詢。他們的速度只同是否使用索引有關,如果查詢需要用到復合索引,用 UNION ALL 執行的效率更高。

b13b5b1c1f9a590d5dfd212560dc31c1.png

盡量UNION ALL 代替 UNION UNIONUNION ALL 的差異主要是前者需要將結果集合并后再進行唯一性過濾操作,會涉及到排序,增加大量的CPU運算,加大資源消耗及延遲。當然,UNION ALL的前提條件是兩個結果集沒有重復數據。


避免在WHERE 子句中對索引列使用 IN 和 NOT IN

應盡量避免在 WHERE 子句中使用 IN 和 NOT IN ,否則將導致全表掃描,對于連續的數值,能用 BETWEEN AND 盡量避免使用 IN。一般,用 EXISTS 代替 IN 。若需要使用 IN,在 IN 后面值的列表中,按照值的分布數量降序排列,減少判斷的次數。

嘗試使用BETWEEN AND 替換 IN 。

0a271b35c1d0520b56592e92a8f55e06.png

我們使用 EXISTS 替代 IN,用 NOT EXISTS 替代 NOT IN,無論在哪種情況下, NOT IN 效率都是最低的。

93f41a442a11385a711f45aadf84ad74.png

嘗試使用LEFT JOIN 替換 IN。

4e3a697e27606a39fd55668268fbd6dd.png

如上,我們使用了如下方式優化了 IN NOT IN

  • 使用 between 替換 in ( 如果 in 的條件是連續的)
  • 使用 exists 替代 in、用not exists替代 not in
  • 使用 left join 替換 in

避免在WHERE 子句中對索引列使用計算、函數、類型轉換等操作

應盡量避免在 WHERE 子句中對 “=” 左邊的字段進行函數、算術運算及其他表達式運算,可以將表達式運算移至“=”右邊,否則將導致引擎放棄使用索引而進行全表掃描。

bad36e6328d16b19ca70aa3bb4dc695b.png
6bfcb21c47d92eab5e8fbf1590a0edde.png

?


避免在WHERE 子句中對索引列使用參數

如果在 WHERE 子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時。它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項,可以改為強制查詢使用索引。

8e261f6c3fcaa2ee6afbfac6da02739c.png

使用合理的分頁方式以提高分頁的效率

分頁查詢在我們的實際應用中非常普遍,也是最容易出問題的查詢場景。比如對于下面簡單的語句,一般想到的辦法是在name,age,register_time字段上創建復合索引。這樣條件排序都能有效的利用到索引,性能迅速提升。

18fbb604a9510e7366702dfbef84c0cb.png

如上例子,當 LIMIT 子句變成 “LIMIT 100000, 50” 時,此時我們會發現,只取50條語句為何會這么慢?

原因很簡單,MySQL并不知道第 100000條記錄從什么地方開始,即使有索引也需要從頭計算一次,因此會感覺非常的慢,一般我們在做翻頁時,是可以獲取上一頁中的某個數據標志來縮小查詢范圍的,比如時間,可以將上一頁的最大值時間作為查詢條件的一部分,SQL可以優化為這樣:

9154d3fedf043503a43be5f9c209eb63.png

使用EXISTS 替換 DISTINCT

EXISTS語句用來判斷()內的表達式是否存在返回值,如果存在就返回 True,如果不存在就返回 False,同時它只要括號中的表達式有一個值存在,就立刻返回 True ,而不用遍歷表中所有的數據。因此 EXISTS 使查詢效率更高。

793101241ebaca6a8496fe134cce4f6f.png

避免在WHERE 子句中對索引列進行 NULL 值判斷

應盡量避免在 WHERE 子句中對字段進行 NULL 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,創建表時 NULL 是默認值,但大多數時候應該使用 NOT NULL,或者使用一個默認值,如 0 作為默認值。

例如,性別,使用1表示男,2表示女,0表示未知或者是用戶沒有選擇,默認值設置為 0,因為大部分編程語言的數字類型的默認值0。

ac3e3dad7a5567a74f731bd237fff949.png

空值和NULL是有區別的,以一個杯子為例:

  • 空值 代表杯子是真空的。
  • NULL 代表杯子中裝滿了空氣。

如果字段允許為空,可能會有以下問題:

  • 查詢條件就必須處理為空的情況,否則會出現一些很奇怪的問題,比如 NOT IN、!= 等負向條件查詢在有 NULL 值的情況下返回永遠為空結果,查詢容易出錯。
  • 在部分數據庫中會導致索引失效
  • 可空列需要更多的存儲空間,導致空間變大,進而導致數據庫系統查詢分析變的復雜。
  • 在程序中也需要每次都判斷是不是空,導致程序復雜了。

但凡事沒有絕對的,使用默認值的思路可以解決很大一部分可為空的問題,但不是所有都需這樣做,具體還是要根據具體業務進行分析。


避免在WHERE 子句中對索引列進行隱式類型轉換

當我們對不同類型的值進行比較的時候,為了使得這些數值可比較,MySQL會做一些隱式轉化(Implicit type conversion)。

SQL查詢語句的條件中字段賦值與字段定義類型不匹配是一種常見的錯誤用法。

88232acd665d4501b0987aabafcff979.png

如上,字段 account 的定義為 varchar 類型,在 WHERE 條件中 account 字段是數字型,兩者數據類型不一樣,這時是沒法直接進行比較的,需要進行類型轉換。MySQL的策略是將表中 account 字段全部轉換為數字型之后再比較,由于函數作用于表字段,引起索引失效,導致全表掃描,正確的寫法如下:

efbf36021b0437259e40997cbcb08dc2.png

合理使用復合索引

69d1fc39d0ac91edf75ee076a806670c.png

如果經常執行如上查詢,那么建立三個單獨索引 不如建立一個復合索引,因為三個單獨索引通常數據庫每次執行只能使用其中一個,雖然這樣比不使用索引而進行全表掃描提高了很多效率,但使用復合索引因為索引本身就對應到三個字段上的,效率會有更大提高。

那么為什么數據庫只支持一條查詢語句只使用一個索引,簡單的講是因為N個獨立索引同時在一條語句使用的效果比只使用一個索引還要慢,開銷太大

在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用,并且應盡可能的讓字段順序與索引順序相一致。

同時,復合索引的生效原則是從前往后依次使用生效,如果中間某個索引沒有使用,那么斷點前面的索引部分起作用,斷點后面的索引沒有起作用,造成斷點的原因一般有:

  • 前邊的任意一個索引沒有參與查詢,后面的不生效。
  • 前邊的任意一個索引失效,當前索引及后面全部不生效。
  • 前邊的任意一個索引字段參與的是范圍查詢,后面的不生效。

引發索引失效,導致全表掃描的原因有:

  • 索引列進行計算、函數、類型轉換等操作。
  • 索引列使用不等于,如 != <>
  • 索引列使用 IS NULL ,IS NOT NULL
  • 模糊查詢LIKE 以通配符開頭如,%str
  • 索引列使用使用 OR 來連接條件。
  • 索引列使用 NOT IN
  • 類型錯誤,如字段 NUM 類型 為varcharWHERE 條件用 numberNUM = 1
  • WHERE子句和 ORDER BY使用相同的索引,并且 ORDER BY的順序和索引順序相同,并且 ORDER BY 的字段都是升序或者降序,否則不會使用索引。
  • 復合索引不符合最佳左前綴原則或存在斷點
  • 如果MYSQL評估使用索引比全表掃描更慢,則不使用索引。

例如我們建立了一個這樣復合索引key index (col1, col2, col3),那么其實相當于創建了(col1),(col1, col2),(col1, col2, col3) 三個索引,即最佳左前綴特性。

f7eb1ed62069d006ebb28c8982728fcc.png

其他 優化 技巧

當索引列有大量數據重復時,SQL查詢可能不會去利用索引,并不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的。如表中有“性別”字段,即使在“性別”字段建立索引也對查詢效率起不了作用,盡量不要對數據庫中某個含有大量重復的值的字段建立索引。


建立索引可以提高 SELECT 的效率,但 索引并不是越多越好。索引同時也降低了 INSERT 及 UPDATE 的效率,因為 INSERT 或 UPDATE 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視實際應用情況而定。同時,一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用的字段是否有建立索引的必要。


對于數值字段,盡量使用數字型字段,若只含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對于數字型而言,只需要比較一次就夠了。

對于字符型字段,盡量的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長字段存儲空間小,可以節省存儲空間,其次對于查詢來說,在一個相對較小的字段內搜索效率顯然要高些。


避免使用 select * from table,用具體的字段列表代替“*”,避免返回用不到的任何字段。


盡可能的使用索引字段作為查詢條件,尤其是聚簇索引,必要時可以通過index index_name來強制指定索引,避免對大表查詢時進行table scan,必要時考慮新建索引。要注意索引的維護,周期性重建索引,重新編譯存儲過程。


在新建臨時表時,如果一次性插入數據量很大,那么可以使用 SELECT INTO 代替 CREAT TABLE,避免造成產生大量日志 ,以提高速度。如果數據量不大,為了緩和系統表的資源,應先CREAT TABLE,然后INSERT。


當服務器的內存夠多時,配置 線程數量 = 最大連接數 + 5,使其發揮最大的效率。否則使用配置 線程數量 < 最大連接數啟用SQL SERVER的線程池來解決,如果還是 線程數量 = 最大連接數+5,可能會嚴重的損害服務器的性能。


盡量避免向客戶端返回大量結果數據,若數據量過大,應該考慮相應需求是否合理。盡量避免大事務操作,提高系統并發能力。


創建索引的一般規則

  • 表的主鍵、外鍵需要建立索引。
  • 頻繁與其他表進行連接的表,在連接字段上應該建立索引。
  • 頻繁出現在 WHERE 子句及 ORDER BY 中的字段,特別是大表的字段,應該建立索引。
  • 索引應該建在短字段上,對于大的文本字段甚至超長字段,避免建索引。
  • 復合索引的建立需要結合實際應用進行分析,盡量考慮用單字段索引代替。
  • 正確選擇復合索引中的主列字段,一般是選擇性較好的字段;
  • 復合索引的幾個字段是否經常同時以 AND 方式出現在 WHERE 子句中,單字段查詢是否極少甚至沒有,如果是,則可以建立復合索引,否則考慮單字段索引。
  • 如果復合索引中包含的字段經常單獨出現在 WHERE 子句中,則分解為多個單字段索引。
  • 如果復合索引所包含的字段超過3個,需要結合實際應用考慮其必要性,考慮減少復合的字段。
  • 如果既有單字段索引,又有這幾個字段上的復合索引,通常可以刪除復合索引。
  • 頻繁進行數據操作的表,不要建立太多的索引,刪除無用的索引。
  • 建立的每個索引都會增加存儲開銷,索引對于插入、刪除、更新操作也會增加處理上的開銷。另外,過多的復合索引,在有單字段索引的情況下,一般都是沒有存在價值的。相反,還會降低數據增加刪除時的性能,特別是對頻繁更新的表來說,負面影響非常大。
  • 盡量不要對數據庫中某個含有大量重復的值的字段建立索引。
409e635ce86d429ca6bfabe77d56f6db.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272928.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272928.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272928.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

b樣條和三次樣條_樣條曲線

最近在學習軌跡規劃中的軌跡生成&#xff0c;涉及到樣條曲線方面的知識&#xff0c;總結一下。二次樣條三次樣條曲線平滑曲線的平滑性和相應的平滑性的評判準則相關&#xff0c;在[1]中&#xff0c;作者采用曲率的平方和曲率導數的平方作為評判準則其中 是路徑點的方向角。最小…

數字圖像處理

題目&#xff1a;大規模圖像中的目標檢測與分類方法 在進行圖像目標識別與跟蹤時&#xff0c;攝像機所采集的圖像&#xff0c;在成像、數字化以及傳輸過程中&#xff0c;難免會受到各種各樣噪聲的干擾&#xff0c;圖像的質量往往會出現不盡人意的退化&#xff0c;影響了圖像的視…

2015年秋季個人閱讀計劃

10月閱讀計劃&#xff1a;《軟件需求模式》 10月12日23:59前發表第一篇讀書筆記。 10月22日23:59前發表第二篇讀書筆記。 10月31日23:59前發表第三篇讀書筆記。 11月閱讀計劃&#xff1a;需求模式——軟件建模與分析 11月12日23:59前發表第一篇讀書筆記。 11月22日23:59前發表第…

內容可編輯_讓PDF像WORD一樣自由編輯,好用的PDF編輯工具推薦

在日常工作中&#xff0c;我們經常要和PDF文件打交道。以往編輯PDF文件&#xff0c;比如修改文字等&#xff0c;需要下載專門的PDF編輯軟件&#xff0c;通常編輯器都會超過200M&#xff0c;下載安裝很麻煩&#xff0c;還會擠壓電腦的儲存空間&#xff0c;影響運行速度。當迅讀P…

DHL 快遞跟蹤查詢

思路描述&#xff1a;主要使用正則表達式解析。 返回一個跟蹤步驟列表。 public class TrackingData { public string time { get; set; } public string context { get; set; } } public class DHLExpressTrackingHelper { private static string urlFormat "http://web…

會返回兩次_嫦娥五號為何用獨特的半彈道式返回方式?原來有更深遠的考慮……...

更多戰史及裝備評說&#xff0c;請移步公眾號asiavikin&#xff08;轉載請注明出處&#xff09;24日凌晨4時30分&#xff0c;嫦娥五號在文昌航天發射場由長征五號火箭成功送入地月轉移軌道&#xff0c;22時6分完成第一次軌道修正&#xff0c;可喜可賀。這是人類44年來首度去月球…

【轉】VS2013中如何解決error C4996: 'fopen'問題

原文網址&#xff1a;http://jingyan.baidu.com/article/ce436649fd61543773afd32e.html 今天編寫控制臺應用程序時出現如下錯誤 error C4996: fopen: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_…

中關鍵字 表示空類型_C語言數據類型

程序在運行時要做的內容就是處理數據。程序要解決復雜的問題&#xff0c;就要處理不同的數據。不同的數據都是以自己本身的一種特定形式存在的&#xff0c;不同的數據類型占用不同的存儲空間。C語言中有多種不同的數據類型&#xff0c;其中包括幾個大的方向&#xff1a;基本數據…

理解inode

。 理解inode 一、inode是什么&#xff1f; 理解inode&#xff0c;要從文件儲存說起。 文件儲存在硬盤上&#xff0c;硬盤的最小存儲單位叫做"扇區"&#xff08;Sector&#xff09;。每個扇區儲存512字節&#xff08;相當于0.5KB&#xff09;。 操作系統讀取硬盤的時…

幀同步_微信小游戲接入“熊孩子噩夢”健康系統 幀同步能力上線

3月31日&#xff0c;微信小游戲官方公眾號“做個小游戲”發文宣布全新面向未成年人保護的健康系統已經上線&#xff0c;該系統聯動“成長守護平臺”的功能&#xff0c;可以更好助力家長群體對于未成年人游戲行為的監管。另外就在昨天&#xff0c;微信小游戲也曝光了另外一項新能…

【js】獲得項目路徑

1 var curWwwPathwindow.document.location.href; 2 //獲取主機地址之后的目錄&#xff0c;如&#xff1a; uimcardprj/share/meun.jsp 3 var pathNamewindow.document.location.pathname; 4 var poscurWwwPath.indexOf(pathName); //獲取主機地址&#xff0c;如&…

寫一個python程序、求解使得npv值為零的折現率_計算題專題:凈現值NPV分析與習題...

凈現值(NPV)是反映投資方案在計算期內獲利能力的動態評價指標。投資方案的凈現值是指用一個預定的基準收益率(或設定的折現率)i&#xff0c;分別把整個計算期間內各年所發生的凈現金流量都折現到投資方案開始實施時的現值之和。今天的一分錢要比明天的一分錢值錢NPV—計算公式和…

Myeclipse 安裝Aptana3.2 插件

轉自&#xff08;http://www.cnblogs.com/yinger/archive/2011/08/29/2157193.html&#xff09; 安裝步驟&#xff1a; 1、下載aptana3.2 Eclipse Plugin插件. 下載地址&#xff1a;http://update1.aptana.org/studio/3.2/024747/index.html 2、在java文件夾下新建文件夾plugin…

python語言的取余運算符_Python 中用于整數除法取余的運算符是()_學小易找答案...

【填空題】隱球菌病多由()傳播。【單選題】下列選項中,哪一個符號是管道符號。 ( )【多選題】可采用分批法計算產品成本的企業有( )【填空題】現有字符串 s”1234567” ,則 s[::2] 得到子串 , s[-1:0:-2] 得到子串【單選題】關于 Python 格式控制,下列說法正確的是()【單選題】…

Linux系統初級優化

系統參數優化和怎樣增強系統安全性&#xff0c;系統默認的一些參數都是比較保守的&#xff0c;所以我們可以通過調整系統參數來提高系統內存、CPU、內核資源的占用&#xff0c;通過禁用不必要的服務、端口&#xff0c;來提高系統的安全性&#xff0c;更好的發揮系統的可用性。通…

python3 selenium安裝教程_Python3爬蟲利器之Selenium的安裝

Selenium是一個自動化測試工具&#xff0c;利用它我們可以驅動瀏覽器執行特定的動作&#xff0c;如點擊、下拉等操作。對于一些JavaScript渲染的頁面來說&#xff0c;這種抓取方式非常有效。下面我們來看看Selenium的安裝過程。1. 相關鏈接官方網站&#xff1a;http://www.sele…

【原創】SQlServer數據庫生成簡單的說明文檔小工具(附源碼)

這是一款簡單的數據庫文檔生成工具&#xff0c;主要實現了SQlServer生成說明文檔的小工具&#xff0c;目前不夠完善&#xff0c;主要可以把數據庫的表以及表的詳細字段信息&#xff0c;導出到Word中&#xff0c;可以方便開發人員了解數據庫的信息或寫技術說明文檔。技術上主要采…

php導出excel時間錯誤(同一個時間戳,用date得到不同的時間)

通過在date之前設置時區解決了 date_default_timezone_set("Asia/Shanghai"); $schedule_time date("Y-m-d H:i:s", 1443234565);轉載于:https://www.cnblogs.com/bushe/p/4840463.html

封裝成vla函數_第四章:Python之函數

第一節&#xff1a;函數入門與定義函數理解函數所謂函數&#xff0c;就是為一段實現特定功能的代碼“取”個名字&#xff0c;以后即可通過該名字來執行(調用)這段代碼從邏輯上看&#xff0c;函數相當于一個黑匣子定義函數的語法定義函數的三條鐵律函數需要幾個關鍵的、需要動態…

sqlhelper中事務的簡單用法(初學者)

自己的博客sql1"INSERT INTO tablename(Id,col1,col2) VALUES(Id,col1,col2) update tablename2 set colcol";sql2"INSERT INTO tablename3(Id,col1,col2) VALUES(Id,col1,col2)";//參數設置&#xff08;略&#xff09;using(SqlTransaction tran SqlHel…