如何分析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; (說明:關閉自動分析統計)。
在Oracle中SQL語句的解析步驟是怎樣的呢
在Oracle中SQL語句的解析步驟如下: 1、 語法檢測。
判斷一條SQL語句的語法是否符合SQL的規范,比如執行:SQL> selet * from emp;我們就可以看出由于Select關鍵字少了一個“c”,這條語句就無法通過語法檢驗的步驟了。 2、 語義檢查。
語法正確的SQL語句在解析的第二個步驟就是判斷該SQL語句所訪問的表及列是否準確?用戶是否有權限訪問或更改相應的表或列?比如如下語句: SQL> select * from emp; select * from emp * ERROR at line 1: ORA-00942: table or view does not exist 由于查詢用戶沒有可供訪問的emp對象,因此該SQL語句無法通過語義檢查。 3、 檢查共享池中是否有相同的語句存在。
假如執行的SQL語句已經在共享池中存在同樣的副本,那么該SQL語句將會被軟解析,也就是可以重用已解析過的語句的執行計劃和優化方案,可以忽略語句解析過程中最耗費資源的步驟,這也是我們為什么一直強調避免硬解析的原因。 這個步驟又可以分為兩個步驟: (1)驗證SQL語句是否完全一致。
在這個步驟中,Oracle將會對傳遞進來的SQL語句使用HASH函數運算得出HASH值,再與共享池中現有語句的HASH值進行比較看是否一一對應。現有數據庫中SQL語句的HASH值我們可以通過訪問v$sql、v$sqlarea、v$sqltext等數據字典中的HASH_VALUE列查詢得出。
如果SQL語句的HASH值一致,那么ORACLE事實上還需要對SQL語句的語義進行再次檢測,以決定是否一致。那么為什么Oracle需要再次對語句文本進行檢測呢?不是SQL語句的HASH值已經對應上了?事實上就算是SQL語句的HASH值已經對應上了,并不能說明這兩條SQL語句就已經可以共享了。
我們首先參考如下一個例子:假如用戶A有自己的一張表EMP,他要執行查詢語句:select * from emp;用戶B也有一張EMP表,同樣要查詢select * from emp;這樣他們兩條語句在文本上是一模一樣的,他們的HASH值也會一樣,但是由于涉及到查詢的相關表不一樣,他們事實上是無法共享的。 假如這時候用戶C又要查詢同樣一條語句,他查詢的表為scott下的公有同義詞,還有就是SCOTT也查詢同樣一張自己的表emp,情況會是如何呢? SQL> connect a/a Connected。
SQL> create table emp ( x int ); Table created。 SQL> select * from emp; no rows selected SQL> connect b/b Connected。
SQL> create table emp ( x int ); Table created。 SQL> select * from emp; no rows selected SQL> conn scott/tiger Connected。
SQL> select * from emp; SQL> conn c/c Connected。 SQL> select * from emp; SQL> conn/as sysdba Connected。
SQL> select address,hash_value, executions, sql_text 2 from v$sql 3 where upper(sql_text) like 'SELECT * FROM EMP%' 4 / ADDRESS HASH_VALUE EXECUTIONS SQL_TEXT -------- ---------- ---------- ------------------------ 78B89E9C 3011704998 1 select * from emp 78B89E9C 3011704998 1 select * from emp 78B89E9C 3011704998 2 select * from emp 我們可以看到這四個查詢的語句文本和HASH值都是一樣的,但是由于查詢的對象不同,只有后面兩個語句是可以共享的,不同情況的語句還是需要硬解析的。 因此在檢查共享池共同SQL語句的時候,是需要根據具體情況而定的。
我們可以進一步查詢v$sql_shared_cursor以得知SQL為何不能共享的原因: SQL> select kglhdpar, address, 2 auth_check_mismatch, translation_mismatch 3 from v$sql_shared_cursor 4 where kglhdpar in 5 ( select address 6 from v$sql 7 where upper(sql_text) like 'SELECT * FROM EMP%' ) 8 / KGLHDPAR ADDRESS A T -------- -------- - - 78B89E9C 786C9D78 N N 78B89E9C 786AC810 Y Y 78B89E9C 786A11A4 Y Y TRANSLATION_MISMATCH表示SQL游標涉及到的數據對象是不同的;AUTH_CHECK_MISMATCH表示對同樣一條SQL語句轉換是不匹配的。 ( 2、)驗證SQL語句執行環境是否相同。
比如同樣一條SQL語句,一個查詢會話加了/*+ first_rows */的HINT,另外一個用戶加/*+ all_rows */的HINT,他們就會產生不同的執行計劃,盡管他們是查詢同樣的數據。 我們下面就一個實例來說明SQL執行環境對解析的影響,我們通過將會話的workarea_size_policy變更來查看對同樣一條SQL語句執行的影響: SQL> alter system flush shared_pool; System altered。
SQL> show parameter workarea_size_policy NAME TYPE VALUE ------------------------------------ ----------- -------------- workarea_size_policy string AUTO SQL> select count(*) from t; COUNT(*) ---------- 5736 SQL> alter session set workarea_size_policy=manual; Session altered。 SQL> select count(*) from t; COUNT(*) ---------- 5736 SQL> select sql_text, child_number, hash_value, address 2 from v$sql 3 where upper(sql_text) = 'SELECT COUNT(*) FROM T' 4 / SQL_TEXT CHILD_NUMBER HASH_VALUE ADDRESS ------------------------------ ------------ ---------- -------- select count(*) from t 0 2199322426 78717328 select count(*) from t 1 2199322426 78717328 可以看到。
數據庫語句解析
1、定義數據庫連接字符串:String strCon=”server=localhost;database=Northwind;Truseted-Connection=Yes;” 2、執行的sql語句:server strqry=”select*fromCatefories”;3、利用1中定義的連接字符串連接數據庫,得到一個句柄SqlConnection con=new SqlConnection(strCon);4、打開3中連接到數據庫的句柄,換句話說是連接到數據庫,這樣就可以執行2中定義的sql語句了。
*();---以上,希望對你有所幫助。
數據庫語句解析
1、定義數據庫連接字符串:
String strCon=”server=localhost;database=Northwind;Truseted-Connection=Yes;”
2、執行的sql語句:
server strqry=”select*fromCatefories”;
3、利用1中定義的連接字符串連接數據庫,得到一個句柄
SqlConnection con=new SqlConnection(strCon);
4、打開3中連接到數據庫的句柄,換句話說是連接到數據庫,這樣就可以執行2中定義的sql語句了。
*();
---
以上,希望對你有所幫助。
oracle sql是怎么解析的
導讀:Oracle的后臺運作原理是什么?我們的一條命令是如何被執行的?今天我們就從一條簡單的Select語句開始,看看Oracle數據庫后臺的運作機制。
Select語句可以說是DBA和數據庫開發者在工作中使用最多的語句之一,但這條語句是如何執行?在Oracle數據庫中又是如何運作的呢?今天我們就從一條簡單的Select語句開始,看看Oracle數據庫后臺的運作機制。這對于我們之后的系統管理與故障排除非常有幫助。
第一步:客戶端把語句發給服務器端執行當我們在客戶端執行select語句時,客戶端會把這條SQL語句發送給服務器端,讓服務器端的進程來處理這語句。也就是說,Oracle客戶端是不會做任何的操作,他的主要任務就是把客戶端產生的一些SQL語句發送給服務器端。
雖然在客戶端也有一個數據庫進程,但是,這個進程的作用跟服務器上的進程作用事不相同的。服務器上的數據庫進程才會對SQL語句進行相關的處理。
不過,有個問題需要說明,就是客戶端的進程跟服務器的進程是一一對應的。也就是說,在客戶端連接上服務器后,在客戶端與服務器端都會形成一個進程,客戶端上的我們叫做客戶端進程;而服務器上的我們叫做服務器進程。
所以,由于所有的SQL語句都是服務器進程執行的,所以,有些人把服務器進程形象地比喻成客戶端進程的“影子”。第二步:語句解析當客戶端把SQL語句傳送到服務器后,服務器進程會對該語句進行解析。
同理,這個解析的工作,也是在服務器端所進行的。雖然這只是一個解析的動作,但是,其會做很多“小動作”。
1. 查詢高速緩存。服務器進程在接到客戶端傳送過來的SQL語句時,不會直接去數據庫查詢。
而是會先在數據庫的高速緩存中去查找,是否存在相同語句的執行計劃。如果在數據高速緩存中,剛好有其他人使用這個查詢語句的話,則服務器進程就會直接執行這個SQL語句,省去后續的工作。
所以,采用高速數據緩存的話,可以提高SQL語句的查詢效率。一方面是從內存中讀取數據要比從硬盤中的數據文件中讀取數據效率要高,另一方面,也是因為這個語句解析的原因。
不過這里要注意一點,這個數據緩存跟有些客戶端軟件的數據緩存是兩碼事。有些客戶端軟件為了提高查詢效率,會在應用軟件的客戶端設置數據緩存。
由于這些數據緩存的存在,可以提高客戶端應用軟件的查詢效率。但是,若其他人在服務器進行了相關的修改,由于應用軟件數據緩存的存在,導致修改的數據不能及時反映到客戶端上。
從這也可以看出,應用軟件的數據緩存跟數據庫服務器的高速數據緩存不是一碼事。2. 語句合法性檢查。
當在高速緩存中找不到對應的SQL語句時,則數據庫服務器進程就會開始檢查這條語句的合法性。這里主要是對SQL語句的語法進行檢查,看看其是否合乎語法規則。
如果服務器進程認為這條SQL語句不符合語法規則的時候,就會把這個錯誤信息,反饋給客戶端。在這個語法檢查的過程中,不會對SQL語句中所包含的表名、列名等等進行SQL他只是語法上的檢查。
3. 語言含義檢查。若SQL語句符合語法上的定義的話,則服務器進程接下去會對語句中的字段、表等內容進行檢查。
看看這些字段、表是否在數據庫中。如果表名與列名不準確的話,則數據庫會就會反饋錯誤信息給客戶端。
所以,有時候我們寫select語句的時候,若語法與表名或者列名同時寫錯的話,則系統是先提示說語法錯誤,等到語法完全正確后,再提示說列名或表名錯誤。若能夠掌握這個順序的話,則在應用程序排錯的時候,可以節省時間。
4. 獲得對象解析鎖。當語法、語義都正確后,系統就會對我們需要查詢的對象加鎖。
這主要是為了保障數據的一致性,防止我們在查詢的過程中,其他用戶對這個對象的結構發生改變。對于加鎖的原理與方法,我在其他文章中已經有專門敘述,在這里就略過不談了。
5. 數據訪問權限的核對。當語法、語義通過檢查之后,客戶端還不一定能夠取得數據。
服務器進程還會檢查,你所連接的用戶是否有這個數據訪問的權限。若你連接上服務器的用戶不具有數據訪問權限的話,則客戶端就不能夠取得這些數據。
故,有時候我們查詢數據的時候,辛辛苦苦地把SQL語句寫好、編譯通過,但是,最后系統返回個 “沒有權限訪問數據”的錯誤信息,讓我們氣半死。這在前端應用軟件開發調試的過程中,可能會碰到。
所以,要注意這個問題,數據庫服務器進程先檢查語法與語義,然后才會檢查訪問權限。6. 確定最佳執行計劃。
當語句與語法都沒有問題,權限也匹配的話,服務器進程還是不會直接對數據庫文件進行查詢。服務器進程會根據一定的規則,對這條語句進行優化。
不過要注意,這個優化是有限的。一般在應用軟件開發的過程中,需要對數據庫的sql語言進行優化,這個優化的作用要大大地大于服務器進程的自我優化。
所以,一般在應用軟件開發的時候,數據庫的優化是少不了的。當服務器進程的優化器確定這條查詢語句的最佳執行計劃后,就會將這條SQL語句與執行計劃保存到數據高速緩存。
如此的話,等以后還有這個查詢時,就會省略以上的語法、語義與權限檢查的步驟,而直接執行SQL語句,提高SQL。