SQL查詢優化

来源:https://www.cnblogs.com/anyv/archive/2019/03/11/10511929.html
-Advertisement-
Play Games

SQL優化是老生常談的話題。隨著關係型資料庫的發展,資料庫內部現在可以進行一些優化。在查詢分析,查詢檢查,資料庫內部會代數優化和物理優化之後再執行。但是,這需要我們理解資料庫內部規律才能進行。現在,我們需要找出RDBMS的優化規律,以寫出適合RDBMS自動優化的SQL語句。只看SQL優化總結,可以翻 ...


        SQL優化是老生常談的話題。隨著關係型資料庫的發展,資料庫內部現在可以進行一些優化。在查詢分析,查詢檢查,資料庫內部會代數優化和物理優化之後再執行。但是,這需要我們理解資料庫內部規律才能進行。現在,我們需要找出RDBMS的優化規律,以寫出適合RDBMS自動優化的SQL語句。只看SQL優化總結,可以翻到文章末尾。

        先談談資料庫內部的代數優化和物理優化,就是查詢優化主要的兩個部分。資料庫查詢過程的代價有IO,cpu,通信代價,記憶體代價,但是最要就是IO代價。

查詢優化的優點       1、用戶不必考慮如何最好地表達查詢以獲得較好的效率                2、系統可以比用戶程式的“優化”做得更好

代數優化,按照一定的規則,通過對關係代數表達式進行等價變換,改變代數表達式中操作的次序和組合,使查詢執行更高效。公式有很多,例如

1.連接、笛卡爾積交換律

2. 連接、笛卡爾積的結合律

物理優化,就是要選擇高效合理的操作演算法或存取路徑,求得優化的查詢計劃

1)基於規則的啟髮式優化

啟髮式規則是指那些在大多數情況下都適用,但不是在每種情況下都是最好的規則。

2)基於代價估算的優化

優化器估算不同執行策略的代價,並選出具有最小代價的執行計劃。

3)兩者結合的優化方法:

常常先使用啟髮式規則,選取若幹較優的候選方案,減少代價估算的工作量

(定性)選擇操作

對於小關係,使用全表順序掃描,即使選擇列上有索引

對於大關係,啟髮式規則有:

1)對於選擇條件是“主碼=值”的查詢,查詢結果最多是一個元組,可以選擇主碼索引,一般的RDBMS會自動建立主碼索引

2)對於選擇條件是“非主屬性=值”的查詢,並且選擇列上有索引,要估算查詢結果的元組數目,如果比例較小(<10%)可以使用索引掃描方法,否則還是使用全表順序掃描

3)對於選擇條件是屬性上的非等值查詢或者範圍查詢,並且選擇列上有索引,要估算查詢結果的元組數目,如果比例較小(<10%)可以使用索引掃描方法,否則還是使用全表順序掃描

4)對於用AND連接的合取選擇條件,如果有涉及這些屬性的組合索引,優先採用組合索引掃描方法

5)對於用OR連接的析取選擇條件,一般使用全表順序掃描

(定性)連接操作

1)如果2個表都已經按照連接屬性排序:選用排序-合併演算法

2)如果一個表在連接屬性上有索引,選用索引連接演算法

3)如果上面2個規則都不適用,其中一個表較小,選用Hash join演算法

(定量)工作量估計:

全表掃描演算法              普通的全表掃描,cost=B                         選擇條件是“碼=值”,那麼平均搜索代價 cost=B/2 

索引掃描演算法             若為B+樹,層數為L,需要存取B+樹中從根結點到葉結點L塊,再加上基本表中該元組所在的那一塊,所以cost=L+1

                                   如果比較條件是>,>=,<,<=操作,假設有一半的元組滿足條件,就要存取一半的葉結點,通過索引訪問一半的表存儲塊,cost=L+Y/2+B/2

排序-合併連接演算法     如果連接表已經按照連接屬性排好序,則cost=Br+Bs+(Frs*Nr*Ns)/Mrs         

                                   如果必須對文件排序還需要在代價函數中加上排序的代價       對於包含B個塊的文件排序的代價大約是  (2*B)+(2*B*log2B)

根據以上理論,實際操作和他人經驗,可以總結如下一些規律(僅供參考):

1.對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。一個表的索引不能過多,過多不利於刪除,插入等操作。

2.應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設置預設值0,確保表中num列沒有null值,然後這樣查詢:
select id from t where num=0

3.應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。

4.應儘量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=205.in 和 not in 也要慎用,否則會導致全表掃描,如: select id from t where num in(1,2,3) 對於連續的數值,能用 between 就不要用 in 了: 

select id from t where num between 1 and 3
6.下麵的查詢也將導致全表掃描:
select id from t where name like '%abc%'
7.應儘量避免在 where 子句中對欄位進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改為:
select id from t where num=100*2
8.應儘量避免在where子句中對欄位進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id
應改為:
select id from t where name like 'abc%'
9.不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
10.在使用索引欄位作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,
否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。
11.不要寫一些沒有意義的查詢,如需要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
create table #t(...)
12.很多時候用 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)
13.並不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重覆時,SQL查詢可能不會去利用索引, 如一表中有欄位sex,male、female幾乎各一半,那麼即使在sex上建了索引也對查詢效率起不了作用。 
14.索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率, 因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定
一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。
15.儘量使用數字型欄位,若只含數值信息的欄位儘量不要設計為字元型,這會降低查詢和連接的性能,並會增加存儲開銷。 這是因為引擎在處理查詢和連接時會逐個比較字元串中每一個字元,而對於數字型而言只需要比較一次就夠了。 
16.儘可能的使用 varchar 代替 char ,因為首先變長欄位存儲空間小,可以節省存儲空間, 其次對於查詢來說,在一個相對較小的欄位內搜索效率顯然要高些。 

17.任何地方都不要使用 select * from t ,用具體的欄位列表代替“*”,不要返回用不到的任何欄位。
18.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。

 

     本文在自己學習和他人經驗之上,提煉而成。初次寫作,文章多有不足之處,不吝賜教。

文章引用:https://blog.csdn.net/jie_liang/article/details/77340905

                  http://www.cnblogs.com/smartloli/p/4356660.html




您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • docker 網路分為單機和多機,我們來瞭解一下docker的單機網路 docker單機網路分為以下幾種: 1)bridge NetWork,使用--net=bridge指定,預設設置。2)Host NetWork ,使用--net=host指定。3)None NetWork,使用--net=non ...
  • 課程簡介:本課程從高頻知識內容入手,全面解析提分,以使各位考生在有限的時間內,達到最理想的成績。本課程適應於以下情況的考生:1)有一定基礎,但備考時間不足2)雖然複習時間多,但抓不到重點3)在複習備考過程中,有疑難未決的4)想通過突擊,提分通過資料庫系統工程師考試的講師簡介:清哥 某機構高級金牌講師 ...
  • 課程簡介:本課程從高頻知識內容入手,全面解析提分,以使各位考生在有限的時間內,達到最理想的成績。本課程適應於以下情況的考生:1)有一定基礎,但備考時間不足2)雖然複習時間多,但抓不到重點3)在複習備考過程中,有疑難未決的4)想通過突擊,提分通過資料庫系統工程師考試的講師簡介:清哥 某機構高級金牌講師 ...
  • 一、創建虛擬機 1、從網上下載一個Centos6.X的鏡像(http://vault.centos.org/) 2、安裝一臺虛擬機配置如下:cpu1個、記憶體1G、磁碟分配20G(看個人配置和需求,本人配置有點低所以參數有點低) 3、虛擬機安裝建議去挑戰minidesktop,分區自己創建有/boot ...
  • 筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》 (本篇內圖片均來自丁奇老師的講解,如有侵權,請聯繫我刪除) 10) --MySQL為什麼有時會選錯索引? MySQL中的一張表上可以支持多個索引的,但是,往往你寫SQL語句的時候不會去主動指定使用哪個索引。也就是說,使用哪個索引是由MySQL來 ...
  • 我們在網站開發中,涉及MySQL資料庫查詢時,常常需要將兩個表或多個表聯合起來進行查詢數據,這就用到了MySQL中的JOIN函數。 JOIN函數有三種,分別是: LEFT JOIN 左連接查詢: 查詢兩個表中共有的數據,並以左邊的表為基準顯示左表的全部數據,顯示右表符合條件的數據, 不足的地方顯示N ...
  • 條件查詢 使用Where進行數據篩選結果為True的會出現在結果集裡面 select 欄位 from 表名 where 條件; # 例: select * from test_table where id > 2; # 篩選出id大於2的所有欄位 比較運算符 等於= 大於> 大於等於>= 小於< 小 ...
  • connect by 用於存在父子,祖孫,上下級等層級關係的數據表進行層級查詢。 語法格式: { CONNECT BY [ NOCYCLE ] condition [AND condition]... [ START WITH condition ] | START WITH condition C ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...