當前位置:商標查詢大全網 - 教育培訓 - 如何優化SQL語句

如何優化SQL語句

(1)選擇最有效的表名順序(僅在基於規則的優化器中有效):

ORACLE的解析器從右到左處理FROM子句中的表名,FROM子句寫入。

最後壹個表(基本表,驅動表)將首先被處理,FROM子句包含多個表。

在這種情況下,必須選擇記錄數最少的表作為基本表。如果有三個以上的表連接查詢

,那麽就需要選擇交集表作為基本表,而交集表指的是

他的表所引用的表。

(where子句中的連接順序。;

ORACLE以自下而上的順序解析WHERE子句。根據這個原則,表之間的連接必須是

必須寫在其他WHERE條件之前,那些能篩選出最大記錄數的條件必須寫在WHERE中。

子句的結尾。

(3)避免在select子句中使用' * ':

在解析的過程中,ORACLE會依次將' * '轉換成所有的列名。這項工作是通過

查詢數據字典,意味著要花更多的時間。

⑷減少訪問數據庫的次數:

ORACLE內部做了很多工作:解析SQL語句,估計索引的利用率,綁定變更。

數量、讀取數據塊等。;

(5)重置SQL*Plus、SQL*Forms和Pro*C中的ARRAYSIZE參數可以增加

每次數據庫訪問檢索的數據量,建議值為200。

(6)使用解碼功能減少處理時間:

使用DECODE函數可以避免重復掃描相同的記錄或連接相同的表。

(7)簡單的集成和無關的數據庫訪問:

如果您有幾個簡單的數據庫查詢語句,您可以將它們集成到壹個查詢中(即使

它們之間沒有關系)

(8)刪除重復記錄:

刪除重復記錄的最有效方法示例(因為使用了ROWID):

從EMP E中刪除WHERE E . ROWID & gt(選擇最小值(X.ROWID)

FROM EMP X其中X . EMP _ NO = E . EMP _ NO);

(9)用截斷替換刪除:

刪除表中的記錄時,壹般情況下,使用回滾段來保存。

放可以恢復的信息。如果沒有提交事務,ORACLE將在刪除前恢復數據。

的狀態(確切地說,是還原到執行delete命令之前的狀態),當使用TRUNCATE時,它返回。

滾動部分不再存儲任何可以恢復的信息。命令運行時,數據無法恢復,所以很少見。

當資源被調用時,執行時間會很短。(譯者按:TRUNCATE只刪除整個表。

TRUNCATE是DDL,不是DML

(10)盡可能使用提交:

只要有可能,就在程序中盡可能多地使用COMMIT,這樣程序的性能提高了,需求也

將因提交釋放的資源而減少:

提交釋放的資源:

A.用於恢復回滾段上的數據的信息。

B.程序語句獲得的鎖

C.重做日誌緩沖區的空間

D.ORACLE管理上述三種資源中的內部費用。

將HAVING子句替換為Where子句:

避免使用HAVING子句。只有在檢索了所有記錄之後,才會對結果集執行HAVING。

過濾。這個過程需要排序和合計等操作。如果WHERE子句可以限制記錄的數量,

那會降低這方面的成本。(不在甲骨文中)on,where,having都可以加。

在壹個片段的子句中,on是第壹個被執行的,其次是where,having是最後壹個,因為on是第壹個放不符合項的子句。

只有篩選出壹條記錄後才能進行統計,這樣可以減少中間操作中要處理的數據,本來應該是

速度是最快的,並且應該比having快,因為它在求和之前過濾數據

當連接兩個表時,使用on,因此當連接壹個表時,只有where與having進行比較。

在這種單表查詢統計的情況下,如果要過濾的條件不涉及要計算的字段,那麽它們

結果是壹樣的,只是拉什莫爾技術可以用在速度上,而不能用在速度上

後者速度較慢。如果涉及計算字段,則表示該字段的值不在計算之前。

當然,按照上壹篇文章寫的工作流程,where的動作時間是在計算之前完成的,而

Having只有在計算後才起作用,所以在這種情況下,結果會有所不同。在多

當表聯接查詢時,on比where更早工作。首先,根據表格之間的連接情況,

將多個表組合成壹個臨時表後,按where篩選,然後計算,再按

必須過濾。因此,如果妳想讓過濾條件發揮正確的作用,妳必須先理解這篇文章。

應該什麽時候起作用,然後再決定放在哪裏。

(12)減少對表的查詢:

在帶有子查詢的SQL語句中,應該特別註意減少對表的查詢。示例:

從表中選擇TAB_NAME,其中(TAB_NAME,DB_VER) = ( SELECT

TAB_NAME,DB_VER FROM TAB_COLUMNS其中VERSION = 604)

(13)通過內部函數提高SQL效率。

復雜的SQL經常犧牲執行效率。能夠掌握以上利用函數解決問題的方法。

在實際工作中很有意義。

(14)使用表格的別名:

當在SQL語句中連接多個表時,使用表的別名並將別名作為每列的前綴。

這樣可以減少解析時間,減少列歧義導致的語法錯誤。

(15)將IN替換為EXISTS,將NOT IN替換為NOT EXISTS

在許多基於基本表的查詢中,為了滿足壹個條件,通常需要連接另壹個表。

那麽,在這種情況下,使用EXISTS(或NOT EXISTS)通常會提高查詢的效率。

在查詢中,NOT IN子句將執行內部排序和合並。在這兩種情況下,不在是

效率最低(因為它對子查詢中的表執行全表遍歷)。避免使用NOT IN。

我們可以將其重寫為外部連接或不存在。

示例:

(高效)SELECT * FROM EMP(基本表)其中EMPNO >;0且存在(選擇

“x”來自部門,其中部門編號=員工。DEPTNO和LOC = 'MELB ')

(低效)SELECT * FROM EMP(基本表)其中EMPNO >;0和DEPTNO IN(選擇

部門編號來自部門位置= 'MELB ')

(16)識別“低效執行”SQL語句:

雖然目前各種關於SQL優化的圖形化工具層出不窮,但是我們自己編寫SQL工具。

解決問題總是最好的辦法:

SELECT執行,DISK_READS,BUFFER_GETS,ROUND((BUFFER_GETS-

DISK_READS)/BUFFER_GETS,2) Hit_radio,ROUND(DISK_READS/EXECUTIONS,2)

每次運行的讀取次數,

SQL _ TEXT FROM V $ SQLAREA WHERE EXECUTIONS & gt;0和BUFFER _ GETS & gt0和

(BUFFER _ GETS-DISK _ READS)/BUFFER _ GETS & lt;0.8階由4 desc;

(17)利用索引提高效率;

索引是表的概念部分,用於提高檢索數據的效率。ORACLE使用復雜的。

雜項自平衡B樹結構。通常,通過索引查詢數據比掃描整個表要快。當ORACLE尋找它時,

在尋找執行查詢和更新語句的最佳路徑時,ORACLE優化器將使用索引。

對多個表使用壹個索引也可以提高效率。使用索引的另壹個優點是它提供了壹個主鍵。

(主鍵)的唯壹性驗證。那些LONG或者LONG RAW數據類型,妳幾乎可以索引。

所有列。通常,在大型表中使用索引特別有效。當然,妳也會發現當掃描小

表,使用索引也可以提高效率。雖然使用索引可以提高查詢效率,但是我們

我們還必須註意它的成本。索引需要空間來存儲,並且需要定期維護。每當中有記錄時

當添加或刪除表或者修改索引列時,索引本身也會被修改。這意味著插入每條記錄。

,DELETE,UPDATE會為此多付出4到5倍的磁盤I/O,因為索引需要額外的存儲。

存儲空間和處理,那些不必要的索引會降低查詢響應時間。定期重建索引。

這是必要的。;

更改索引& ltINDEXNAME & gt重建& lt表空間名稱& gt

(18)將DISTINCT替換為EXISTS:

當提交包含壹對多信息表(如部門表和雇員表)的查詢時,應避免使用。

在SELECT子句中使用DISTINCT。壹般可以考慮用EXIST代替,這樣查詢速度更快。

速度,因為RDBMS核心模塊會在子查詢的條件滿足時立即返回結果。示例:

(低效):從部門d、員工e中選擇不同的部門編號、部門名稱

其中,部門編號=部門編號(有效):從部門中選擇部門編號、部門名稱。

D .存在的位置(從EMP E中選擇“X”,其中E . DEPT _ NO = D . DEPT _ NO);

(19) sql語句大寫;因為oracle總是先解析sql語句,在執行前將小寫字母轉換成大寫字母。

(20)Java代碼中盡量少用連接符“+”連接字符串!

21)避免在索引列上使用NOT。通常情況下,

我們應該避免使用NOT,NOT索引列,這與在索引列上使用函數具有相同的效果。當“ORACLE”遇到“NOT”時,它將停止使用索引,轉而執行全表掃描。

(22)避免在索引列上使用計算。

在WHERE子句中,如果索引列是函數的壹部分,優化器將使用全表掃描而不是索引。示例:效率低下:

SELECT…FROM DEPT WHERE SAL * 12 & gt;25000;高效:

SELECT … FROM部門SAL & gt25000/12;

(23)使用> =替換>

高效:

SELECT * FROM EMP WHERE DEPTNO & gt=4低效:

SELECT * FROM EMP WHERE DEPTNO & gt兩者的區別在於,前者DBMS會直接跳轉到DEPT等於4的第壹條記錄,而後者會先定位DEPTNO=3等於3的記錄,然後向前掃描到DEPT大於3的第壹條記錄。

(24)用UNION替換OR(適用於索引列)

壹般來說,用UNION替換WHERE子句中的OR會有很好的效果。對索引列使用或將導致全表掃描。請註意,上述規則僅對多個索引列有效。如果列沒有索引,查詢效率可能會降低,因為您沒有選擇或。在下面的示例中,LOC_ID和REGION都有索引。高效:select loc _ id,loc _ desc,Region from location where LOC _ ID = 10 union select loc _ id,loc _ desc,Region from location where Region = " Melbourne "低效:select LOC _ ID,LOC _ Desc,Region from location where LOC _ ID = 10 OR Region = " Melbourne "如果堅持使用OR,需要將記錄最少的索引列寫在最前面。

(25)將或改為。

這是壹個簡單易記的規則,但實際執行效果有待檢驗。在ORACLE8i下,兩者的執行路徑似乎是壹樣的。

低效:選擇...從loc _ ID = 10 orloc _ ID = 20 orloc _ ID = 30有效選擇的位置...從loc _ in (10,20,30)的位置;

(26)避免在索引列上使用IS NULL和IS NOT NULL。

避免在索引中使用任何可以為空的列,ORACLE將無法使用該索引。對於單列索引,如果列包含空值,則記錄將不存在於索引中。對於復合索引,如果每壹列都為空,則記錄也不會存在於索引中。如果至少有壹列不為空,則記錄將存在於索引中。例如,如果在表的A列和B列上建立了唯壹索引,並且表中有壹條記錄A,如果B的值為(123,null),則ORACLE不會接受下壹條A和B的值相同(123,null)的記錄(insert)。但是如果所有的索引列都是空的,ORACLE會認為整個鍵值都是空的,空不代表空。因此,可以插入1000條具有相同鍵值的記錄。當然,因為索引列中不存在空值,所以在WHERE子句中比較索引列的空值會導致ORACLE禁用索引。

低效:(索引無效)where dept _ code不為空的部門;高效:(指標有效)select…from dept _ code >;=0;

(27)始終使用索引的第壹列:

如果索引建立在多個列上,優化器將選擇僅當where子句引用其第壹個前導列時才使用索引。這也是壹個簡單而重要的規則。當只引用索引的第二列時,優化器使用全表掃描並忽略該索引。

(28)用UNION-ALL替換UNION(如果可能):

當SQL語句需要兩個UNION的查詢結果集時,這兩個結果集將以UNION-ALL的方式進行合並,然後進行排序,最後輸出結果。如果用UNION ALL代替UNION,排序就沒必要了,效率也會相應提高。應該註意,UNION ALL將在兩個結果集中重復輸出相同的記錄。因此,您應該從業務需求出發,分析使用UNION ALL的可行性。UNION將對結果集進行排序,這個操作將使用內存SORT_AREA_SIZE。對於這個內存的優化也是非常重要的。下面的SQL可以用來查詢排序的消耗。

效率低下:

從借方交易中選擇ACCT數量、余額金額

其中TRAN _日期= ' 365438+95年12月0日'工會選擇ACCT _數量,余額_金額

從debt _ transactions,其中trans _ date = ' 31-dec-95 ' Efficient:SELECT ACCT _編號,余額_金額。

從借方交易,其中TRAN日期= ' 365438+95年12月0日' UNIONALLSELECT ACCT數量,余額金額

從借方交易,其中TRAN日期='31-DEC-95 '?

(29)將ORDER改為WHERE:

ORDER BY子句僅在兩個嚴格的條件下使用索引。

ORDER BY中的所有列必須包含在同壹個索引中,並保持索引中的順序。

ORDER BY中的所有列都必須定義為非空。

WHERE子句中使用的索引和ORDER BY子句中使用的索引不能並置。

例如,表DEPT包含以下列:

DEPT_CODE主鍵不為空

DESC部門不為空

部門類型為空

低效:(不使用索引)按dept _ type從部門順序中選擇dept _ code高效:(使用索引)從dept _ type > 0的部門中選擇dept _ code?

(30)避免改變索引列的類型;

在比較不同數據類型的數據時,ORACLE會自動對列執行簡單的類型轉換。

假設EMPNO是壹個數字類型的索引列。select…from EMP where EMPNO = ' 123 '事實上,經過ORACLE類型轉換後,該語句轉換為:select…from EMP where EMPNO = to _ NUMBER(' 123 ')。幸運的是,索引列上沒有發生類型轉換,索引的用途也沒有改變。現在,假設EMP_TYPE是字符類型的索引列。select…from EMP where EMP _ type = 123的語句被ORACLE轉換為:select…from EMP where to _ number(EMP _ type)= 123。由於內部類型轉換,此索引將不會更改。為了避免ORACLE對您的SQL進行隱式類型轉換,最好是顯式地表達類型轉換。註意,在用數值比較字符時,ORACLE會優先將數值型轉換為字符型?

31)要註意的WHERE子句:

某些SELECT語句中的WHERE子句不使用索引。這裏有壹些例子。在下面的例子中,(1)'!= '將不使用索引。請記住,索引只能告訴您表中存在什麽,而不能告訴您表中不存在什麽。(2)' || '是壹個字符連接函數。與其他功能壹樣,索引是禁用的。(3)‘+’是壹個數學函數。就像其他數學函數壹樣,索引被禁用。(4)相同的索引列不能相互比較,這將

(32) A .如果檢索數據超過表中記錄的30%,使用索引不會有明顯的效率提升。

B.在某些情況下,使用索引可能比全表掃描慢,但兩者的數量級相同。通常使用索引比全表掃描快幾倍甚至幾千倍!

(33)避免使用消耗資源的操作:

帶有DISTINCT、UNION、MINUS、intersect和order by的SQL語句將啟動SQL引擎來執行消耗資源的排序功能。Distinct需要執行壹次排序操作,而其他distinct至少需要執行兩次排序操作。通常,使用union、minus,INTERSECT的SQL語句可以用其他方式重寫。如果妳的數據庫的SORT_AREA_SIZE分配的很好,UNION,MINUS,INTERSECT也可以考慮。畢竟它們可讀性很強。

(34)通過以下方式優化組:

為了提高GROUP BY語句的效率,我們可以在GROUP BY之前過濾掉不必要的記錄。以下兩個查詢返回相同的結果,但是第二個查詢顯然快得多。

效率低下:

選擇職務,AVG(薩爾)

從職務=“總裁”或職務=“經理”有效的員工組職務:

選擇職務,AVG(薩爾)

來自電磁脈沖

其中JOB =“總統”

或JOB = 'MANAGER '組作業

我們來看看甲骨文的執行流程。

分析SQL語句在Orcle中是如何工作的。

a、用戶發送SQL請求並打開遊標;

b .將SQL語句語法分析、執行計劃、數據字典等信息存入內存* * *共享池;

c .將數據文件中的相關數據塊讀入數據緩沖區;

d .執行相應的操作,如果修改,先添加行級鎖,確認後,將修改前後記錄的內容存入重做日誌緩沖區;

e .將結果返回給用戶並關閉光標。

註意:SQL語句區分大小寫。如果相同的語句區分大小寫,

不壹樣,oracle需要執行兩次分析,每句話後面都要跟“;”結束。