1. oracle sql的執行計劃如何查看
方法/步驟
打開PL/SQL Developer軟體,請確保plsql能夠成功連接到一個oracle資料庫。
在PL/SQL Developer中寫好一段SQL代碼,按F5,或者點擊「執行執行計劃」圖標,PL/SQL Developer會自動打開執行計劃窗口,顯示該SQL的執行計劃。
可以看到窗口上方是sql語句,下方顯示執行計劃表格。表格的列主要包含描述、用戶、對象、成本花費、IO開銷等,表格,當然表格列還可以自定義。表格的行包含了查詢邏輯的執行順序和各個步驟信息。
執行計劃表格內容的執行順序是:按照從左至右,從上至下的步驟執行,具體是指執行計劃按照層次逐步縮進,從左至右看,縮進最多的那一步最先執行,如果縮進量相同,則按照從上而下的方法判斷執行順序。
通過查看執行計劃表格的cost列,即成本花費能夠知道哪個步驟花費的成本高,通過查看執行計劃表格的行中的objectname列,能夠知道是否使用到表中的索引。
步驟閱讀
6
本文先簡單介紹在plsql中的使用方法,後續會逐步完成各種理論和技巧的使用方法,例如優化器、表連接訪問方法、索引等
2. SQL與DBMS的關系
1、DBMS 是 DataBaseManagentSystem
也就是資料庫管理系統
比如 Oracle MySQL SqlServer。。。都是
2、SQL是結構化查詢語言--也就是幾個資料庫系統通用的語言
3、SQL語句必須在某個資料庫系統上才能運行 就是這個關系
3. sql執行的作業是串列還是並行的
oracle 10g的DBMS_XPLAN包中display_cursor函數不同於display函數,display_cursor用於顯示SQL語句的真實的執行計劃,在大多數情況下,
顯示真實的執行計劃有助於更好的分析SQL語句的全過程,尤其是運行此SQL語句實時的I/O開銷。通過對比預估的I/O與真實的I/O開銷來判斷
SQL語句所存在問題,如缺少統計信息,SQL語句執行的次數,根據實際中間結果集的大小來選擇合適的連接方式等。本文僅僅講述
display_cursor函數的使用。
一、display_cursor函數用法
1、display_cursor函數語法
DBMS_XPLAN.DISPLAY_CURSOR(
sql_id IN VARCHAR2 DEFAULT NULL,
cursor_child_no IN NUMBER DEFAULT NULL,
format IN VARCHAR2 DEFAULT 'TYPICAL');
2、display_cursor函數參數描述
sql_id
指定位於庫緩存執行計劃中SQL語句的父游標。默認值為null。當使用默認值時當前會話的最後一條SQL語句的執行計劃將被返回
可以通過查詢V$SQL 或V$SQLAREA的SQL_ID列來獲得SQL語句的SQL_ID。
cursor_child_no
指定父游標下子游標的序號。即指定被返回執行計劃的SQL語句的子游標。默認值為0。如果為null,則sql_id所指父游標下所有子游標
的執行計劃都將被返回。
format
控制SQL語句執行計劃的輸出部分,即哪些可以顯示哪些不顯示。使用與display函數的format參數與修飾符在這里同樣適用。
除此之外當在開啟statistics_level=all時或使用gather_plan_statistics提示可以獲得執行計劃中實時的統計信息
有關詳細的format格式描述請參考:dbms_xplan之display函數的使用 中format參數的描述
下面給出啟用統計信息時format新增的修飾符
iostats 控制I/O統計的顯示
last 默認,顯示所有執行計算過的統計。如果指定該值,則只顯示最後一次執行的統計信息
memstats 控制pga相關統計的顯示
allstats 此為iostats memstats的快捷方式,即allstats包含了iostats和memstats
run_stats_last 等同於iostats last。只能用於oracle 10g R1
run_stats_tot 等同於iostats。只能用於oracle 10g R1
抓一個最近一小時最消耗IO的SQL:
SELECT sql_id, COUNT(*)
FROM gv$active_session_history ash, gv$event_name evt
WHERE ash.sample_time > SYSDATE - 1 / 24
AND ash.session_state = 'WAITING'
AND ash.event_id = evt.event_id
AND evt.wait_class = 'User I/O'
GROUP BY sql_id
ORDER BY COUNT(*) DESC;
執行上面的SQL:
SQL> SELECT sql_id, COUNT(*)
FROM gv$active_session_history ash, gv$event_name evt
2 3 WHERE ash.sample_time > SYSDATE - 1 / 24
4 AND ash.session_state = 'WAITING'
5 AND ash.event_id = evt.event_id
6 AND evt.wait_class = 'User I/O'
7 GROUP BY sql_id
8 ORDER BY COUNT(*) DESC;
SQL_ID COUNT(*)
------------- ----------
g7fu6qba82m6b 668
63r47zyphdk06 526
9f5m4wd88nc1h 514
593p47drw5fhk 232
br91w16jzy4fu 120
4fvwyjpnh6tp7 78
gm0nrbfuj8kzr 70
2184k363hw4xd 68
gc4dajs7g5myy 46
8vrk9sfuwfdgq 42
ccpnb4dwdmq21 40
查看SQL的執行計劃:
SELECT * FROM TABLE(dbms_xplan.display_cursor('g7fu6qba82m6b'));
在SQLPLUS中執行:
SQL> set pagesize 2000
SQL> SELECT * FROM TABLE(dbms_xplan.display_cursor('g7fu6qba82m6b'));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------
SQL_ID g7fu6qba82m6b, child number 0
-------------------------------------
UPDATE "CPDDS_PDATA"."CDM_LEDGER" SET "CSTM_NAME" = :a1,"CSTM_NO" =
:a2,"PAPER_TYPE" = :a3,"PAPER_NO" = :a4,"CURR_TYPE" = :a5,"SVT_NO" =
:a6,"BAL_DIR" = :a7,"BAL" = :a8,"AVAL_BAL" = :a9,"NORM_FRATIO" =
:a10,"PK_BAL" = :a11,"DR_ACCU" = :a12,"CR_ACCU" = :a13,"LAST_TRAN_DATE" =
:a14,"LAST_TRAN_TIME" = :a15,"PRT_LINE_NUM" = :a16,"NOREG_PK_REC_NUM" =
:a17,"PK_NO" = :a18,"PWD" = :a19,"FLAG" = :a20,"FRZ_FLAG" =
:a21,"CARD_HOLD_FLAG" = :a22,"PK_HOLD_FLAG" = :a23,"BGN_INT_DATE" =
:a24,"OPEN_DATE" = :a25,"ACC_HOLD_FLAG" = :a26,"CLS_DATE" =
:a27,"OPEN_TLR" = :a28,"CLS_TLR" = :a29,"CLS_INT" = :a30,"OPEN_INST" =
:a31,"ADD_NUM" = :a32,"DAC" = :a33,"FRZ_TIMES1" = :a34,"FRZ_TIMES2" =
:a35,"HOST_SEQNO" = :a36,"D_UPDATE_DATE" = :a37 WHERE "ACC" = :b0
Plan hash value: 319441092
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | | | 3 (100)| |
| 1 | UPDATE | CDM_LEDGER | | | | |
|* 2 | INDEX UNIQUE SCAN| I_CDM_LEDGER | 1 | 269 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ACC"=:B0)
29 rows selected.
總結
1、與display函數不同,display_cursor顯示的為真實的執行計劃
2、對於format參數,使用與display函數的各個值,同樣適用於display_cursor函數
3、當statistics_level為all或使用gather_plan_statistics提示可以獲得執行時的統計信息
4、根據真實與預估的統計信息可以初步判斷SQL效率低下的原因,如統計信息的准確性、主要的開銷位於那些步驟等
4. 為什麼sql語言的select命令和關系代數表達式相比,dbms更容易進行優化
關系代數表達式由關系代數操作組合而成。操作中,以笛卡爾積和聯接操作最費時,並生成大量的中間結果。如果直接按表達式書寫的順序執行,必將花費很多時間,並生成大量的中間結果,效率較低。在執行前,由DBMS的查詢子系統先對關系代數表達式進行優化,盡可能先執行選擇和投影操作,以便減少中間結果,並節省時間。
5. 在資料庫管理系統(DBMS)VFP中,SQL語句怎麼執行
在可用資料庫欄中選擇你要更新的資料庫
按快捷鍵F5執行
6. 請教一個oracle的問題。本地動態SQL執行,和DBMS_SQL包執行這兩種分別是什麼意思 DBMS_SQL包又是什麼呢
本地執行EXECUTE IMMEIDIATE和DBMS_SQL都是用執行SQL語句的
前者方便,好理解。。適用於一些簡單的,不是特別長,不需要多次循環執行的SQL
後者在多次循環執行方面效率更高。。但使用起來復雜些,不好理解。。但DBMS_SQL支持超長SQL,在復雜的動態SQL語句方面也比EXECUTE IMMEIDIATE好。
EXECUTE IMMEIDIATE對執行的SQL語句有長度限制,過長就不行了。。
7. Oracle SQL條件順序對性能的影響有哪些
在實際操作中有人會問到關於Oracle資料庫中的Where子句的條件書寫順序的正確與否是否會對SQL性能有影響,我的直覺是沒有影響。 因為如果這個順序有影響,Oracle應該早就能夠做到自動優化,但一直沒有關於這方面的確鑿證據。在網上查到的文章,一般認為在RBO優化器模式下無影響(10G開始,預設為RBO優化器模式),而在CBO優化器模式下有影響,主要有兩種觀點: a.能使結果最少的條件放在最右邊,SQL執行是按從右到左進行結果集的篩選的; b.有人試驗表明,能使結果最少的條件放在最左邊,SQL性能更高。 查過oracle8到11G的在線文檔,關於SQL優化相關章節,沒有任何文檔說過where子句中的條件對SQL性能有影響,到底哪種觀點是對的,沒有一種確切的結論,只好自己來做實驗證明。結果表明,我們大家都知道Oracle SQL條件的相關執行是從右到左的,但條件的順序對SQL性能沒有影響。 實驗一:證明了SQL的語法分析是從右到左的 下面的試驗在9i和10G都可以得到相同的結果: 第1條語句執行不會出錯,第2條語句會提示除數不能為零。 Select'ok'FromDualWhere1/0=1And1=2;Select'ok'FromDualWhere1=2And1/0=1;證明了SQL的語法分析是從右到左的。 實驗二:證明了SQL條件的執行是從右到左的 droptabletemp; createtabletemp(t1varchar2(10),t2varchar2(10)); insertintotempvalues('zm','abcde'); insertintotempvalues('sz','1'); insertintotempvalues('sz','2');commit;select*fromtempwhereto_number(t2)1andt1='sz';select*fromtempwheret1='sz'andto_number(t2)1;在9i上執行, 第1條語句執行不會出錯,第2條語句會提示無效的數字 在10G上執行,兩條語句都不會出錯。 說明:9i上源碼天空 實驗三:證明了在10g上SQL條件的執行是從右到左的 CreateOrReplaceFunctionF1(v_InVarchar2)ReturnVarchar2IsBeginDbms_Output.Put_Line('execF1'); Returnv_In;EndF1;/CreateOrReplaceFunctionF2(v_InVarchar2)ReturnVarchar2IsBeginDbms_Output.Put_Line('execF2'); Returnv_In;EndF2;/SQL setserverouton;SQL
8. 新手自學,,請問PL/SQL 怎麼進sql查詢編輯器 具體步驟!先謝了
一、本地動態SQL
本地動態SQL是使用EXECUTE IMMEDIATE語句來實現的。
1、本地動態SQL執行DDL語句:
需求:根據用戶輸入的表名及欄位名等參數動態建表。
create or replace procere proc_test
(
table_name in varchar2, --表名
field1 in varchar2, --欄位名
datatype1 in varchar2, --欄位類型
field2 in varchar2, --欄位名
datatype2 in varchar2 --欄位類型
) as
str_sql varchar2(500);
begin
str_sql:=』create table 』||table_name||』(』||field1||』 』||datatype1||』,』||field2||』 』||datatype2||』)』;
execute immediate str_sql; --動態執行DDL語句
exception
when others then
null;
end ;
以上是編譯通過的存儲過程代碼。下面執行存儲過程動態建表。
SQL> execute proc_test(』dinya_test』,』id』,』number(8) not null』,』name』,』varchar2(100)』);
PL/SQL procere successfully completed
SQL> desc dinya_test;
Name Type Nullable Default Comments
---- ------------- -------- ------- --------
ID NUMBER(8)
NAME VARCHAR2(100) Y
SQL>
到這里,就實現了我們的需求,使用本地動態SQL根據用戶輸入的表名及欄位名、欄位類型等參數來實現動態執行DDL語句。
2、本地動態SQL執行DML語句。
需求:將用戶輸入的值插入到上例中建好的dinya_test表中。
create or replace procere proc_insert
(
id in number, --輸入序號
name in varchar2 --輸入姓名
) as
str_sql varchar2(500);
begin
str_sql:=』insert into dinya_test values(:1,:2)』;
execute immediate str_sql using id,name; --動態執行插入操作
exception
when others then
null;
end ;
執行存儲過程,插入數據到測試表中。
SQL> execute proc_insert(1,』dinya』);
PL/SQL procere successfully completed
SQL> select * from dinya_test;
ID NAME
1 dinya
在上例中,本地動態SQL執行DML語句時使用了using子句,按順序將輸入的值綁定到變數,如果需要輸出參數,可以在執行動態SQL的時候,使用RETURNING INTO 子句,如:
declare
p_id number:=1;
v_count number;
begin
v_string:=』select count(*) from table_name a where a.id=:id』;
execute immediate v_string into v_count using p_id;
end ;
更多的關於動態SQL中關於返回值及為輸出輸入綁定變數執行參數模式的問題,請讀者自行做測試。
二、使用DBMS_SQL包
使用DBMS_SQL包實現動態SQL的步驟如下:A、先將要執行的SQL語句或一個語句塊放到一個字元串變數中。B、使用DBMS_SQL包的parse過程來分析該字元串。C、使用DBMS_SQL包的bind_variable過程來綁定變數。D、使用DBMS_SQL包的execute函數來執行語句。
1、使用DBMS_SQL包執行DDL語句
需求:使用DBMS_SQL包根據用戶輸入的表名、欄位名及欄位類型建表。
create or replace procere proc_dbms_sql
(
table_name in varchar2, --表名
field_name1 in varchar2, --欄位名
datatype1 in varchar2, --欄位類型
field_name2 in varchar2, --欄位名
datatype2 in varchar2 --欄位類型
)as
v_cursor number; --定義游標
v_string varchar2(200); --定義字元串變數
v_row number; --行數
begin
v_cursor:=dbms_sql.open_cursor; --為處理打開游標
v_string:=』create table 』||table_name||』(』||field_name1||』 』||datatype1||』,』||field_name2||』 』||datatype2||』)』;
dbms_sql.parse(v_cursor,v_string,dbms_sql.native); --分析語句
v_row:=dbms_sql.execute(v_cursor); --執行語句
dbms_sql.close_cursor(v_cursor); --關閉游標
exception
when others then
dbms_sql.close_cursor(v_cursor); --關閉游標
raise;
end;
以上過程編譯通過後,執行過程創建表結構:
SQL> execute proc_dbms_sql(』dinya_test2』,』id』,』number(8) not null』,』name』,』varchar2(100)』);
PL/SQL procere successfully completed
SQL> desc dinya_test2;
Name Type Nullable Default Comments
---- ------------- -------- ------- --------
ID NUMBER(8)
NAME VARCHAR2(100) Y
SQL>
2、使用DBMS_SQL包執行DML語句
需求:使用DBMS_SQL包根據用戶輸入的值更新表中相對應的記錄。
查看錶中已有記錄:
SQL> select * from dinya_test2;
ID NAME
1 Oracle
2 CSDN
3 ERP
SQL>
建存儲過程,並編譯通過:
create or replace procere proc_dbms_sql_update
(
id number,
name varchar2
)as
v_cursor number; --定義游標
v_string varchar2(200); --字元串變數
v_row number; --行數
begin
v_cursor:=dbms_sql.open_cursor; --為處理打開游標
v_string:=』update dinya_test2 a set a.name=:p_name where a.id=:p_id』;
dbms_sql.parse(v_cursor,v_string,dbms_sql.native); --分析語句
dbms_sql.bind_variable(v_cursor,』:p_name』,name); --綁定變數
dbms_sql.bind_variable(v_cursor,』:p_id』,id); --綁定變數
v_row:=dbms_sql.execute(v_cursor); --執行動態SQL
dbms_sql.close_cursor(v_cursor); --關閉游標
exception
when others then
dbms_sql.close_cursor(v_cursor); --關閉游標
raise;
end;
執行過程,根據用戶輸入的參數更新表中的數據:
SQL> execute proc_dbms_sql_update(2,』csdn_dinya』);
PL/SQL procere successfully completed
SQL> select * from dinya_test2;
ID NAME
1 Oracle
2 csdn_dinya
3 ERP
SQL>
執行過程後將第二條的name欄位的數據更新為新值csdn_dinya。這樣就完成了使用dbms_sql包來執行DML語句的功能。
使用DBMS_SQL中,如果要執行的動態語句不是查詢語句,使用DBMS_SQL.Execute或DBMS_SQL.Variable_Value來執行,如果要執行動態語句是查詢語句,則要使用DBMS_SQL.define_column定義輸出變數,然後使用DBMS_SQL.Execute, DBMS_SQL.Fetch_Rows, DBMS_SQL.Column_Value及DBMS_SQL.Variable_Value來執行查詢並得到結果。