從哪些方面,sql語句性能如何分析
一段SQL代碼寫好以后,可以通過查看SQL的執行計劃,初步預測該SQL在運行時的性能好壞,尤其是在發現某個SQL語句的效率較差時,我們可以通過查看執行計劃,分析出該SQL代碼的問題所在。
1、 打開熟悉的查看工具:PL/SQL Developer。
在PL/SQL Developer中寫好一段SQL代碼后,按F5,PL/SQL Developer會自動打開執行計劃窗口,顯示該SQL的執行計劃。
2、 查看總COST,獲得資源耗費的總體印象
一般而言,執行計劃第一行所對應的COST(即成本耗費)值,反應了運行這段SQL的總體估計成本,單看這個總成本沒有實際意義,但可以拿它與相同邏輯不同執行計劃的SQL的總體COST進行比較,通常COST低的執行計劃要好一些。
3、 按照從左至右,從上至下的方法,了解執行計劃的執行步驟
執行計劃按照層次逐步縮進,從左至右看,縮進最多的那一步,最先執行,如果縮進量相同,則按照從上而下的方法判斷執行順序,可粗略認為上面的步驟優先執行。每一個執行步驟都有對應的COST,可從單步COST的高低,以及單步的估計結果集(對應ROWS/基數),來分析表的訪問方式,連接順序以及連接方式是否合理。
4、 分析表的訪問方式
表的訪問方式主要是兩種:全表掃描(TABLE ACCESS FULL)和索引掃描(INDEX SCAN),如果表上存在選擇性很好的索引,卻走了全表掃描,而且是大表的全表掃描,就說明表的訪問方式可能存在問題;若大表上沒有合適的索引而走了全表掃描,就需要分析能否建立索引,或者是否能選擇更合適的表連接方式和連接順序以提高效率。
5、 分析表的連接方式和連接順序
表的連接順序:就是以哪張表作為驅動表來連接其他表的先后訪問順序。
表的連接方式:簡單來講,就是兩個表獲得滿足條件的數據時的連接過程。主要有三種表連接方式,嵌套循環(NESTED LOOPS)、哈希連接(HASH JOIN)和排序-合并連接(SORT MERGE JOIN)。我們常見得是嵌套循環和哈希連接。
嵌套循環:最適用也是最簡單的連接方式。類似于用兩層循環處理兩個游標,外層游標稱作驅動表,Oracle檢索驅動表的數據,一條一條的代入內層游標,查找滿足WHERE條件的所有數據,因此內層游標表中可用索引的選擇性越好,嵌套循環連接的性能就越高。
哈希連接:先將驅動表的數據按照條件字段以散列的方式放入內存,然后在內存中匹配滿足條件的行。哈希連接需要有合適的內存,而且必須在CBO優化模式下,連接兩表的WHERE條件有等號的情況下才可以使用。哈希連接在表的數據量較大,表中沒有合適的索引可用時比嵌套循環的效率要高。
如何分析SQL語句 -
多時候,我們不太清楚自己寫的SQL語句好還是不好,往往數據量一大,程序運行變慢。
其實在SQL/PLUS里可以很清晰的分析出SQL語句的執行計劃,它可以提醒我們來創建索引或改變SQL語句的寫法。 先在sys用戶下運行@/ORACLE_HOME/sqlplus/admin/*內容:set echo ondrop role plustrace;create role plustrace;grant select on v_$sesstat to plustrace;grant select on v_$statname to plustrace;grant select on v_$session to plustrace;grant plustrace to dba with admin option;set echo off產生plustrace角色,然后在sys用戶下把此角色賦予一般用戶&usernameSQL> grant plustrace to &username; 然后找到/ORACLE_HOME/rdbms/admin/*,然后在當前用戶SQL>下運行,它創建一個plan_table,用來存儲分析SQL語句的結果。
create table PLAN_TABLE ( statement_id varchar2(30), timestamp date, remarks varchar2(80), operation varchar2(30), options varchar2(30), object_node varchar2(128), object_owner varchar2(30), object_name varchar2(30), object_instance numeric, object_type varchar2(30), optimizer varchar2(255), search_columns number, id numeric, parent_id numeric, position numeric, cost numeric, cardinality numeric, bytes numeric, other_tag varchar2(255), partition_start varchar2(255), partition_stop varchar2(255), partition_id numeric, other long, distribution varchar2(30)); 在SQL/PLUS的窗口運行以下命令 set time on; (說明:打開時間顯示) set autotrace on; (說明:打開自動分析統計,并顯示SQL語句的運行結果) set autotrace traceonly; (說明:打開自動分析統計,不顯示SQL語句的運行結果) 接下來你就運行測試SQL語句,看到其分析統計結果了。一般來講,我們的SQL語句應該避免對大表的全表掃描。
關閉以上功能,在SQL/PLUS的窗口運行以下命令 set time off; (說明:關閉時間顯示) set autotrace off; (說明:關閉自動分析統計)。
寫出高性能SQL語句需要注意什么
(1)整合簡單,無關聯的數據庫訪問: 如果你有幾個簡單的數據庫查詢語句,你可以把它們整合到一個查詢中(即使它們之間沒有關系) (2)刪除重復記錄: 最高效的刪除重復記錄方法 ( 因為使用了ROWID)例子: DELETE FROM EMP E WHERE E。
ROWID > (SELECT MIN(X。ROWID) FROM EMP X WHERE X。
EMP_NO = E。EMP_NO); (3)用TRUNCATE替代DELETE: 當刪除表中的記錄時,在通常情況下, 回滾段(rollback segments ) 用來存放可以被恢復的信息。
如果你沒有COMMIT事務,ORACLE會將數據恢復到刪除之前的狀態(準確地說是恢復到執行刪除命令之前的狀況) 而當運用TRUNCATE時, 回滾段不再存放任何可被恢復的信息。當命令運行后,數據不能被恢復。
因此很少的資源被調用,執行時間也會很短。 (譯者按: TRUNCATE只在刪除全表適用,TRUNCATE是DDL不是DML) (4)選擇最有效率的表名順序(只在基于規則的優化器中有效): ORACLE 的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最后的表(基礎表 driving table)將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。
如果有3個以上的表連接查詢, 那就需要選擇交叉表(intersection table)作為基礎表, 交叉表是指那個被其他表所引用的表。 (5)WHERE子句中的連接順序.: ORACLE采用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾。
(6)SELECT子句中避免使用 ‘ * ‘: ORACLE在解析的過程中, 會將’*' 依次轉換成所有的列名, 這個工作是通過查詢數據字典完成的, 這意味著將耗費更多的時間 (7)減少訪問數據庫的次數: ORACLE在內部執行了許多工作: 解析SQL語句, 估算索引的利用率, 綁定變量 , 讀數據塊等; (8)在SQL*Plus , SQL*Forms和Pro*C中重新設置ARRAYSIZE參數, 可以增加每次數據庫訪問的檢索數據量 ,建議值為200 (9)使用DECODE函數來減少處理時間: 使用DECODE函數可以避免重復掃描相同記錄或重復連接相同的表。 (11) 用Where子句替換HAVING子句: 避免使用HAVING子句, HAVING 只會在檢索出所有記錄之后才對結果集進行過濾。
這個處理需要排序,總計等操作。 如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷。
(非oracle中)on、where、having這三個都可以加條件的子句中,on是最先執行,where次之,having最后,因為on是先把不符合條件的記錄過濾后才進行統計,它就可以減少中間運算要處理的數據,按理說應該速度是最快的,where也應該比having快點的,因為它過濾數據后才進行sum,在兩個表聯接時才用on的,所以在一個表的時候,就剩下where跟having比較了。 在這單表查詢統計的情況下,如果要過濾的條件沒有涉及到要計算字段,那它們的結果是一樣的,只是where可以使用rushmore技術,而having就不能,在速度上后者要慢如果要涉及到計算的字段,就表示在沒計算之前,這個字段的值是不確定的,根據上篇寫的工作流程,where的作用時間是在計算之前就完成的,而having就是在計算后才起作用的,所以在這種情況下,兩者的結果會不同。
在多表聯接查詢時,on比where更早起作用。系統首先根據各個表之間的聯接條件,把多個表合成一個臨時表后,再由where進行過濾,然后再計算,計算完后再由having進行過濾。
由此可見,要想過濾條件起到正確的作用,首先要明白這個條件應該在什么時候起作用,然后再決定放在那里 (12) 減少對表的查詢: 在含有子查詢的SQL語句中,要特別注意減少對表的查詢。 例子: SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604) (13) 通過內部函數提高SQL效率。
: 復雜的SQL往往犧牲了執行效率。 能夠掌握上面的運用函數解決問題的方法在實際工作中是非常有意義的 (14) 使用表的別名(Alias): 當在SQL語句中連接多個表時, 請使用表的別名并把別名前綴于每個Column上。
這樣一來,就可以減少解析的時間并減少那些由Column歧義引起的語法錯誤。 (15) 用EXISTS替代IN、用NOT EXISTS替代NOT IN: 在許多基于基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接。
在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率。 在子查詢中,NOT IN子句將執行一個內部的排序和合并。
無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷)。 為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS。
例子: (高效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND EXISTS (SELECT 'X' FROM DEPT WHERE DEPT。 DEPTNO = EMP。
DEPTNO AND LOC = 'MELB') (低效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND 。
如何寫出高性能SQL語句
優化SQL查詢:如何寫出高性能SQL語句1、首先要搞明白什么叫執行計劃? 執行計劃是數據庫根據SQL語句和相關表的統計信息作出的一個查詢方案,這個方案是由查詢優化器自動分析產生欀如一條SQL語句如果用來從一個10萬條記錄的表中查1條記錄,那查詢優化器會選擇“索引查找”方式,如果該表進行了歸檔,當前只剩下5000條記錄了,那查詢優化器就會改變方案,采用 “全表掃描”方式。
可見,執行計劃并不是固定的,它是“個性化的”。產生一個正確的“執行計劃”有兩點很重要: (1) SQL語句是否清晰地告訴查詢優化器它想干什么? (2) 查詢優化器得到的數據庫統計信息是否是最新的、正確的?2、統一SQL語句的寫法 對于以下兩句SQL語句,程序員認為是相同的,數據庫查詢優化器認為是不同的。
select * from dual select * From dual 其實就是大小寫不同,查詢分析器就認為是兩句不同的SQL語句,必須進行兩次解析。生成2個執行計劃。
所以作為程序員,應該保證相同的查詢語句在任何地方都一致,多一個空格都不行!3、不要把SQL語句寫得太復雜 我經常看到,從數據庫中捕捉到的一條SQL語句打印出來有2張A4紙這么長。一般來說這么復雜的語句通常都是有問題的。
我拿著這2頁長的SQL語句去請教原作者,結果他說時間太長,他一時也看不懂了。可想而知,連原作者都有可能看糊涂的SQL語句,數據庫也一樣會看糊涂。
一般,將一個Select語句的結果作為子集,然后從該子集中再進行查詢,這種一層嵌套語句還是比較常見的,但是根據經驗,超過3層嵌套,查詢優化器就很容易給出錯誤的執行計劃。因為它被繞暈了。
像這種類似人工智能的東西,終究比人的分辨力要差些,如果人都看暈了,我可以保證數據庫也會暈的。 另外,執行計劃是可以被重用的,越簡單的SQL語句被重用的可能性越高。
而復雜的SQL語句只要有一個字符發生變化就必須重新解析,然后再把這一大堆垃圾塞在內存里。可想而知,數據庫的效率會何等低下。
4、使用“臨時表”暫存中間結果 簡化SQL語句的重要方法就是采用臨時表暫存中間結果,但是,臨時表的好處遠遠不止這些,將臨時結果暫存在臨時表,后面的查詢就在tempdb中了,這可以避免程序中多次掃描主表,也大大減少了程序執行中“共享鎖”阻塞“更新鎖”,減少了阻塞,提高了并發性能。5、 OLTP系統SQL語句必須采用綁定變量 select * from orderheader where changetime > '2010-10-20 00:00:01′ select * from orderheader where changetime > '2010-09-22 00:00:01′ 以上兩句語句,查詢優化器認為是不同的SQL語句,需要解析兩次。
如果采用綁定變量 select * from orderheader where changetime > @chgtime @chgtime變量可以傳入任何值,這樣大量的類似查詢可以重用該執行計劃了,這可以大大降低數據庫解析SQL語句的負擔。一次解析,多次重用,是提高數據庫效率的原則。
6、綁定變量窺測 事物都存在兩面性,綁定變量對大多數OLTP處理是適用的,但是也有例外。 比如在where條件中的字段是“傾斜字段”的時候。
“傾斜字段”指該列中的絕大多數的值都是相同的,一張人口調查表,其中“民族”這列,90%以上都是漢族。那么如果一個SQL語句要查詢30歲的漢族人口有多少,那“民族”這列必然要被放在where條件中。
這個時候如果采用綁定變量@nation會存在很大問題。 試想如果@nation傳入的第一個值是“漢族”,那整個執行計劃必然會選擇表掃描。
然后,第二個值傳入的是“布依族”,按理說“布依族”占的比例可能只有萬分之一,應該采用索引查找。但是,由于重用了第一次解析的“漢族”的那個執行計劃,那么第二次也將采用表掃描方式。
這個問題就是著名的“綁定變量窺測”,建議對于“傾斜字段”不要采用綁定變量。7、 只在必要的情況下才使用begin tran SQL Server中一句SQL語句默認就是一個事務,在該語句執行完成后也是默認commit的。
其實,這就是begin tran的一個最小化的形式,好比在每句語句開頭隱含了一個begin tran,結束時隱含了一個commit。 有些情況下,我們需要顯式聲明begin tran,比如做“插、刪、改”操作需要同時修改幾個表,要求要么幾個表都修改成功,要么都不成功。
begin tran 可以起到這樣的作用,它可以把若干SQL語句套在一起執行,最后再一起commit。好處是保證了數據的一致性,但任何事情都不是完美無缺的。
Begin tran付出的代價是在提交之前,所有SQL語句鎖住的資源都不能釋放,直到commit掉。 可見,如果Begin tran套住的SQL語句太多,那數據庫的性能就糟糕了。
在該大事務提交之前,必然會阻塞別的語句,造成block很多。 Begin tran使用的原則是,在保證數據一致性的前提下,begin tran 套住的SQL語句越少越好!有些情況下可以采用觸發器同步數據,不一定要用begin tran。
8、一些SQL查詢語句應加上nolock 在SQL語句中加nolock是提高SQL Server并發性能的重要手段,在oracle中并不需要這樣做,因為oracle的結構更為合理,有undo表空間保存“數據前影”,該數據如果在修改中還未。
請簡述項目中優化sql語句執行效率的方法,從哪些方面,sql語句性能
1. SQL優化的原則是:將一次操作需要讀取的BLOCK數減到最低,即在最短的時間達到最大的數據吞吐量。
調整不良SQL通常可以從以下幾點切入:
? 檢查不良的SQL,考慮其寫法是否還有可優化內容
? 檢查子查詢 考慮SQL子查詢是否可以用簡單連接的方式進行重新書寫
? 檢查優化索引的使用
? 考慮數據庫的優化器
2. 避免出現SELECT * FROM table 語句,要明確查出的字段。
3. 在一個SQL語句中,如果一個where條件過濾的數據庫記錄越多,定位越準確,則該where條件越應該前移。
4. 查詢時盡可能使用索引覆蓋。即對SELECT的字段建立復合索引,這樣查詢時只進行索引掃描,不讀取數據塊。
5. 在判斷有無符合條件的記錄時建議不要用SELECT COUNT (*)和select top 1 語句。
6. 使用內層限定原則,在拼寫SQL語句時,將查詢條件分解、分類,并盡量在SQL語句的最里層進行限定,以減少數據的處理量。
7. 應絕對避免在order by子句中使用表達式。
8. 如果需要從關聯表讀數據,關聯的表一般不要超過7個。
9. 小心使用 IN 和 OR,需要注意In集合中的數據量。建議集合中的數據不超過200個。
10. 用 代替,>;用>;=代替,1000)。應該用如下語句代替:select name from customer inner join order on *er_id=*er_id where *>100。
15. 在WHERE 子句中,避免對列的四則運算,特別是where 條件的左邊,嚴禁使用運算與函數對列進行處理。比如有些地方 substring 可以用like代替。
16. 如果在語句中有not in(in)操作,應考慮用not exists(exists)來重寫,最好的辦法是使用外連接實現。
17. 對一個業務過程的處理,應該使事物的開始與結束之間的時間間隔越短越好,原則上做到數據庫的讀操作在前面完成,數據庫寫操作在后面完成,避免交叉。
18. 請小心不要對過多的列使用列函數和order by,group by等,謹慎使用disti軟件開發t。
19. 用union all 代替 union,數據庫執行union操作,首先先分別執行union兩端的查詢,將其放在臨時表中,然后在對其進行排序,過濾重復的記錄。
當已知的業務邏輯決定query A和query B中不會有重復記錄時,應該用union all代替union,以提高查詢效率。
優化SQL有什么方法
在數據庫應用系統中編寫可執行的SQL語句可以有多種方式實現,但哪一條是最佳方案卻難以確定。
為了解決這一問題,有必要對SQL實施優化。簡單地說,SQL語句的優化就是將性能低下的SQL語句轉換成達到同樣目的的性能更好的SQL語句。
優化SQL語句的原因 數據庫系統的生命周期可以分成: 設計、開發和成品三個階段。在設計階段進行優化的成本最低,收益最大。
在成品階段進行優化的成本最高,收益最小。如果將一個數據庫系統比喻成一座樓房,在樓房建好后進行矯正往往成本很高而收效很小(甚至可能根本無法矯正),而在樓房設計、生產階段控制好每塊磚瓦的質量就能達到花費小而見效高的目的。
為了獲得最大效益,人們常需要對數據庫進行優化。數據庫的優化通常可以通過對網絡、硬件、操作系統、數據庫參數和應用程序的優化來進行。
根據統計,對網絡、硬件、操作系統、數據庫參數進行優化所獲得的性能提升全部加起來只占數據庫應用系統性能提升的40%左右,其余60%的系統性能提升全部來自對應用程序的優化。許多優化專家甚至認為對應用程序的優化可以得到80%的系統性能提升。
因此可以肯定,通過優化應用程序來對數據庫系統進行優化能獲得更大的收益。 對應用程序的優化通常可分為兩個方面: 源代碼的優化和SQL語句的優化。
由于涉及到對程序邏輯的改變,源代碼的優化在時間成本和風險上代價很高(尤其是對正在使用中的系統進行優化) 。另一方面,源代碼的優化對數據庫系統性能的提升收效有限,因為應用程序對數據庫的操作最終要表現為SQL語句對數據庫的操作。
對SQL語句進行優化有以下一些直接原因: 1. SQL語句是對數據庫(數據) 進行操作的惟一途徑,應用程序的執行最終要歸結為SQL語句的執行,SQL語句的效率對數據庫系統的性能起到了決定性的作用。 2. SQL語句消耗了70%~90%的數據庫資源。
3. SQL語句獨立于程序設計邏輯,對SQL語句進行優化不會影響程序邏輯,相對于對程序源代碼的優化,對SQL語句的優化在時間成本和風險上的代價都很低。 4. SQL語句可以有不同的寫法,不同的寫法在性能上的差異可能很大。
5. SQL語句易學,難精通。SQL語句的性能往往同實際運行系統的數據庫結構、記錄數量等有關,不存在普遍適用的規律來提升性能。
傳統的優化方法 SQL程序人員在傳統上采用手工重寫來對SQL語句進行優化。這主要依靠DBA或資深程序員對SQL語句執行計劃的分析,依靠經驗,嘗試重寫SQL語句,然后對結果和性能進行比較以試圖找到性能較佳的SQL語句。
這種做法存在著以下不足: 1. 無法找出SQL語句的所有可能寫法。很可能花費了大量的時間也無法找到性能較佳的SQL語句。
即便找到了某個性能較佳的SQL語句也無法知道是否存在性能更好的寫法。 2. 非常依賴于人的經驗,經驗的多寡往往決定了優化后SQL語句的性能。
3. 非常耗時間。重寫-->校驗正確性-->比較性能,這一循環過程需要大量的時間。
根據傳統的SQL優化工具的功能,人們一般將優化工具分為以下三代產品: 第一代的SQL優化工具是執行計劃分析工具。這類工具對輸入的SQL語句從數據庫提取執行計劃,并解釋執行計劃中關鍵字的含義。
第二代的SQL優化工具只能提供增加索引的建議,它通過對輸入的SQL語句的執行計劃的分析來產生是否要增加索引的建議。這類工具存在著致命的缺點——只分析了一條SQL語句就得出增加某個索引的結論,根本不理會(實際上也無法評估到)增加的索引對整體數據庫系統性能的影響。
第三代工具是利用人工智能實現自動SQL優化。 人工智能自動SQL優化 隨著人工智能技術的發展和在數據庫優化領域應用的深入,在20世紀90年代末優化技術取得了突破性的進展,出現了人工智能自動SQL優化。
人工智能自動SQL優化的本質就是借助人工智能技術,自動對SQL語句進行重寫,找到性能最好的等效SQL語句。LECCO SQL Expert就采用了這種人工智能技術,其SQL Expert支持Oracle、Sybase、MS SQL Server和IBM DB2數據庫平臺。
其突出特點是自動優化SQL語句。除此以外,還可以以人工智能知識庫“反饋式搜索引擎”來重寫SQL語句,并找出所有等效的SQL語句及可能的執行計劃,通過測試運行為應用程序和數據庫自動找到性能最好的SQL語句,提供微秒級的計時; 能夠優化Web應用程序和有大量用戶的在線事務處理中運行時間很短的SQL語句; 能通過比較源SQL和待選SQL的不同之處,為開發人員提供“邊做邊學式訓練”,迅速提高開發人員的SQL編程技能等等。
該工具針對數據庫應用的開發和維護階段提供了數個特別的模塊:SQL語法優化器、PL/SQL集成化開發調試環境(IDE)、掃描器、數據庫監視器等。其核心模塊之一“SQL 語法優化器”的工作原理大致如下:輸入一條源SQL語句,“人工智能反饋式搜索引擎”對輸入的SQL語句結合檢測到的數據庫結構和索引進行重寫,產生N條等效的SQL語句輸出,產生的N條等效SQL語句再送入“人工智能反饋式搜索引擎”進行重寫,直至無法產生新的輸出或搜索限額滿,接下來對輸出的SQL語句進行過濾,選。