Oracle SQL 優化原則(實用篇)

来源:http://www.cnblogs.com/Cs-Bky/archive/2016/11/18/6077230.html
-Advertisement-
Play Games

由於SQL優化優化起來比較複雜,並且還受環境限制,在開發過程中,寫SQL必須遵循以下幾點原則: 1.Oracle 採用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他Where條件之前,那些可以過濾掉最大數量記錄的條件必須寫在Where子句的末尾. 2.Select 語句避免 ...


由於SQL優化優化起來比較複雜,並且還受環境限制,在開發過程中,寫SQL必須遵循以下幾點原則:

1.Oracle 採用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他Where條件之前,那些可以過濾掉最大數量記錄的條件必須寫在Where子句的末尾.

2.Select 語句避免使用 *

當在Select子句中列出所有的COLUMN時,使用動態SQL列引用 *是一個方便的方法.可是,這是一個非常低效的方法.實際上,Oracle在解析的過程中,會將 * 一次轉換成所有的列名,這個工作是通過查詢數據字典完成的,這意味著將耗費更多的時間.

3.使用表的別名

當在Sql語句中離間多個表時,請使用標的別名並把別名首碼每個Column上.這樣一來,就可以減少解析的時間並減少哪些由Column歧義引起的語法錯誤.

註:Column歧義是指由於Sql中不同的表具有相同的Column名,當SQL語句中出現這個Column時,Sql解析器無法判斷這個Column的歸屬.

OracleSql的優化原則:

儘量少用In操作符,基本上所有In操作都可以用Exists代替,用In寫出的Sql的優點是比較容易寫及清晰易懂,但是用In的Sql性能總是比較低的,從Oracle執行的步驟來分析用In的Sql與不用In的Sql有以下區別:

Oracle視圖將其轉換成多個表的連接,如果轉換不成功則先執行In裡面的子查詢,在查詢外層的表記錄,如果轉換成功則直接採用多個表的連接方式查詢.由此可見用In的Sql至少多了一個轉換的過程.一般的Sql都可以轉換成功,但對於含有分組統計等方面的Sql就不能轉換了.

Oralce在執行In子查詢時,首先執行子查詢,將查詢結果放入臨時表再執行住查詢.而Exist則是首先檢查主查詢,然後運行子查詢知道找到第一個匹配項.NotExists比Not In效率稍高.但具體在尋則IN或EXIST操作時,要根據主子表數據量大小來具體考慮.

推薦方案:在業務密集的SQL當中儘量不用IN操作符,不用NOT IN操作符,可以用NOT EXISTS或者外連接+替代

不用'<>'或者'!='操作符.對不等於操作符的處理會造成全表掃描,可以用'<'or'>'代替.

不等於操作符是永遠不會用到索引的,因策對它的處理會造成全表掃描。

推薦方案:

1)a<>0用 a>0 or a<0;

2)a<>''改為 a>''

where子句中出現IS NULL或者 IS NOT NULL時,ORACLE會停止使用索引而執行全表掃描.可以考慮在設計表時,對索引列設置為NOT NULL,這樣就可以用其他操作來取代判斷NULL的操作。

推薦方案:

1) a is not null 改為 a > 0 或者 a > '' 等

2)不允許欄位為空,而用一個卻省值代替空值.

3)建立點陣圖索引(有分區的表不能建,點陣圖索引比較難控制,如欄位值太多索引會使性能下降,多人更新操作會增加數據塊鎖的現象)

當通配符'%'或者'_'作為查詢字元串的第一個字元時,索引不會被使用.

對於有連接的列'||',最後一個連接列索引會無效.儘量避免連接,可以分開連接或者使用不作用在列上的函數替代.

如果索引不是基於函數的,那麼當在Where子句中對索引列使用函數時,索引不再起作用.

Where子句中避免在索引上使用計算,否則將導致索引失效而進行全表掃描.

對數據類型不同的列進行比較時,會使索引失效.

> 及 < 操作符(大於或小於操作符)

大於或小於操作符一般情況下是不用調整的,因為它有索引就會採用索引查找,但有的情況下可以對它進行優化,如一個表有100萬記錄,一個數值型欄位A, 30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。那麼執行A>2與A>=3的效果就有很大的區別了,因為 A>2時ORACLE會先找出為2的記錄索引再進行比較,而A>=3時ORACLE則直接找到=3的記錄索引。

推薦方案:用“>=”替代“>”。

UNION操作符

UNION在進行錶鏈接後會篩選掉重覆的記錄,所以在錶鏈接後會對所產生的結果集進行排序運算,刪除重覆的記錄再返回結果。實際大部分應用中是不會產生重覆的記錄,最常見的是過程表與歷史表UNION。如:

    select * from gc_dfys

    union

    select * from ls_jg_dfys

    這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重覆的記錄,最後返回結果集,如果表數據量大的話可能會導致用磁碟進行排序。

    推薦方案:採用UNION ALL操作符替代UNION,因為UNION ALL操作只是簡單的將兩個結果合併後就返回。

    select * from gc_dfys

    union all

    select * from ls_jg_dfys

LIKE操作符

LIKE 操作符可以應用通配符查詢,裡面的通配符組合可能達到幾乎是任意的查詢,但是如果用得不好則會產生性能上的問題,如LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘X5400%’則會引用範圍索引。一個實際例子:用YW_YHJBQK表中營業編號後面的戶標識號可來查詢營業編號 YY_BH LIKE ‘%5400%’ 這個條件會產生全表掃描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會利用YY_BH的索引進行兩個範圍的查詢,性能肯定大大提高。

SQL書寫的影響(共用SQL語句可以提高操作效率)

同一功能同一性能不同寫法SQL的影響

如一個SQL在A程式員寫的為

    Select * from zl_yhjbqk

    B程式員寫的為

    Select * from dlyx.zl_yhjbqk(帶表所有者的首碼)

    C程式員寫的為

    Select * from DLYX.ZLYHJBQK(大寫表名)

    D程式員寫的為

    Select *  from DLYX.ZLYHJBQK(中間多了空格)

     以上四個SQL在ORACLE分析整理之後產生的結果及執行的時間是一樣的,但是從ORACLE共用記憶體SGA的原理,可以得出ORACLE對每個SQL 都會對其進行一次分析,並且占用共用記憶體,如果將SQL的字元串及格式寫得完全相同則ORACLE只會分析一次,共用記憶體也只會留下一次的分析結果,這不僅可以減少分析SQL的時間,而且可以減少共用記憶體重覆的信息,ORACLE也可以準確統計SQL的執行頻率。

推薦方案:不同區域出現的相同的Sql語句,要保證查詢字元完全相同,以利用SGA共用池,防止相同的Sql語句被多次分析。

查詢表順序的影響

Oracle從右到左處理From子句中的表名,所以在From子句中包含多個表的情況下,將記錄最少的表放在最後。(只在採用RBO優化時有效).

在FROM後面的表中的列表順序會對SQL執行性能影響,在沒有索引及ORACLE沒有對錶進行統計分析的情況下ORACLE會按表出現的順序進行鏈接,由此因為表的順序不對會產生十分耗伺服器資源的數據交叉。(註:如果對錶進行了統計分析, ORACLE會自動先進小表的鏈接,再進行大表的鏈接)。

Order By語句中的非索引列會降低性能,可以通過添加索引的方式處理。嚴格控制在Order By語句中使用表達式

當在Sql語句中連接多個表時,使用表的別名,並將之作為每列的首碼。這樣可以減少解析時間

多利用內部函數提高Sql效率

對條件欄位的一些優化

採用函數處理的欄位不能利用索引,如

substr(hbs_bh,1,4)=’5400’,優化處理:hbs_bh like ‘5400%’

trunc(sk_rq)=trunc(sysdate), 優化處理:sk_rq>=trunc(sysdate) and sk_rq<trunc(sysdate+1)

進行了顯式或隱式的運算的欄位不能進行索引,如:

ss_df+20>50,優化處理:ss_df>30

‘X’||hbs_bh>’X5400021452’,優化處理:hbs_bh>’5400021542’

sk_rq+5=sysdate,優化處理:sk_rq=sysdate-5

hbs_bh=5401002554,優化處理:hbs_bh=’ 5401002554’,註:此條件對hbs_bh 進行隱式的to_number轉換,因為hbs_bh欄位是字元型。

條件內包括了多個本表的欄位運算時不能進行索引

ys_df>cx_df,無法進行優化

qc_bh||kh_bh=’5400250000’,優化處理:qc_bh=’5400’ and kh_bh=’250000’

可能引起全表掃描的操作

在索引列上使用NOT或者“<>”

對索引列使用函數或者計算

NOT IN操作

通配符位於查詢字元串的第一個字元

IS NULL或者IS NOT NULL

多列索引,但它的第一個列並沒有被Where子句引用


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

-Advertisement-
Play Games
更多相關文章
  • 在Linux下安裝Postgresql有二進位格式安裝和源碼安裝兩種安裝方式,這裡用的是二進位格式安裝。各個版本的Linux都內置了Postgresql,所以可直接通過命令行安裝便可。本文用的是Centos6.5。 安裝Postgresql # 安裝postgresql伺服器 yum install... ...
  • [1]定義 [2]比較運算符 [3]修飾關鍵字 [4][NOT]IN [5]存儲查詢結果 ...
  • 第一部分、十道海量數據處理面試題 1、海量日誌數據,提取出某日訪問百度次數最多的那個IP。 首先是這一天,並且是訪問百度的日誌中的IP取出來,逐個寫入到一個大文件中。註意到IP是32位的,最多有個2^32個IP。同樣可以採用映射的方法,比如模1000,把整個大文件映射為1000個小文件,再找出每個小 ...
  • 今天寫的一個mysql存儲過程涉及到對一個傳入參數的字元串截取,然後需要判斷截取字元串進行一系列操作,最開始用select subtring() into 這樣的方法將截取值賦於declare變數直接報錯。 然後使用sql裡面的方法 select @x=subtring() 也行不通,😣。。。然後 ...
  • 在c#中有個Date屬性用於返回日期,其實就是當天0點。 DateTime dtNow = DateTime.Now; DateTime dtNow2 = dtNow.Date; Console.WriteLine("dtNow=" + dtNow); Console.WriteLine("dtNo... ...
  • Redis Desktop Manager是Redis圖形化管理工具,方便管理人員更方便直觀地管理Redis數據。 然而在使用Redis Desktop Manager之前,有幾個要素需要註意: 一、註釋redis.conf文件中的:bind 127.0.0.1(在一段文字之前打#號為註釋) 二、設 ...
  • mysql 官方客戶端 MySQL-Workbench 下載鏈接 http://dev.mysql.com/downloads/workbench/ 具體安裝步驟就不寫了,直接一直下一步就可以了。 下麵說一下基礎操作: 登錄成功後,界面如下所示。其中,區域1顯示的是資料庫伺服器中已經創建的資料庫列表 ...
  • 前面的話 由於編碼錯誤,造成的資料庫中文識別成亂碼或問號的問題非常常見,本文將詳細說明解決辦法 配置文件 解決中文識別問題的第一步是修改mysql的配置文件my.ini 在[client]下添加 在[mysqld]下添加 然後重新啟動服務 資料庫編碼 首先,新建一個資料庫 通過下列代碼查看資料庫的編 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...