介紹繫結變數之前,先介紹sql執行過程和硬解析的概念:
執行sql的過程,會將sql的文字進行hash運算,得到物件的hash值,然後拿hash值,去hash buckets裡遍歷快取物件控制代碼鍊錶,找到對應的快取物件控制代碼,然後就可以得到快取物件控制代碼裡對應sql執行計畫、解析樹等物件,所以執行相同的sql第二次執行時是會比較快的,因為不需要解析獲取執行計畫,解析樹等物件,如果找不到庫快取物件控制代碼,就需要重新解析,這個過程解析過多,容易造成硬解析問題
硬解析:是指oracle在執行目標sql時,在庫快取中找不到可以重用的解析樹和執行計畫,而不得不從頭開始解析目標sql並生成相應的parent cursor和child cursor的過程。ok,上面是sql執行過程的簡單介紹,由此可知,假如sql執行過程,在共享池裡找不到執行計畫、解析樹等就會重現解析sql,生成執行計畫和解析樹等,這個過程是比較耗時間的,所以要想辦法盡量不要重現解析sql,需要執行計畫直接去共享池拿已經生成的軟解析:是指oracle在執行目標sql時,在library cache中找到了匹配的parent cursor和child cursor,並將儲存在child cursor中的解析樹和執行計畫直接拿過來重用,無須從頭開始解析的過程。
舉個例子,select * from sys_user where userid='u10001';
和select * from sys_user where userid='u10002';
,這兩個很類似的sql在執行過程,生成的執行計畫很有可能是不一樣的,也就是說第一條sql執行後,第二條sql繼續執行,假如發現找不到對應執行計畫,就會再解析sql,重現生成session cursor和一對shared cursor(parent cursor和child cursor)
然後,我們不想重新解析sql,有什麼方法?方法就是用繫結變數的方法
繫結變數的典型用法就是用 :variable_name的形式,variable_name是自定義的變數名稱,variabl_name可以是字母、數字或者字母和數字的組合
ok,上面的那種型別的sql,就可以用一條帶繫結變數的sql來表示:
select * from sys_user where userid = :u;
這樣這種型別的一堆sql都只會解析一次,不用每條sql都解析一遍,可以很好的提高系統處理能力
ok,舉個例子說明
環境準備:
/* 隨便建一張表*/
create
table t as
select * from dba_objects;
注意,這些指令碼只能在sqlplus或者plsql客戶端的命令視窗執行
/* 定義繫結變數vid */
sql>
variable vid number;
/* 給繫結變數賦值為2 */
sql>
exec :vid := 2;
在sqlplus或者plsql客戶端的命令視窗執行
/* 通過繫結變數查詢 */
sql> select * from t where object_id = :vid;
/*通過效能檢視查詢sql解析情況*/
select a.*, b.name
from v$sesstat a, v$statname b
where a.statistic# = b.statistic#
and a.sid = (select
distinct
sidfrom v$mystat)
and b.name like
'%parse%';
/* 去共享池查詢一下這種型別的sql資訊*/
select sql_text, parse_calls, executions
from v$sql
where sql_text like
'select * from t where object_id=%';
/* 通過共享池查詢查詢最慢的10條sql*/
select *
from (select parsing_user_id,
executions,
sorts,
command_type,
disk_reads,
sql_text
from v$sqlarea
order
by disk_reads desc)
where
rownum
< 10;
/* sql語句使用繫結變數*/
往t_emp表寫入一條資料,並統計是否執行成功,返回數值
/*dml語句使用繫結變數*/
declare
vc_sql varchar2(2000);
vc_number number;
begin
vc_sql := 'insert into t_emp(empno,ename,job) values(:1,:2,:3)';
execute
immediate vc_sql using
7990,'smith','hr';
vc_number := sql%rowcount;
dbms_output.put_line(to_char(vc_number));
commit;
end;
/
所以繫結變數在pl/sql裡的核心語法為:
execute
immediate [sql語句] using [變數]
例子來自要實現的的是批量繫結變數,fetch關鍵字,將empno大於7900的職員資訊列印出來
declare
cur_emp sys_refcursor;
vc_sql varchar2(2000);
type namelist is table of varchar2(10);
enames namelist;
cn_batch_size constant pls_integer := 1000;
begin
vc_sql:= 'select ename from t_emp where empno > :1';
open cur_emp for vc_sql using 7900;
loop
fetch cur_emp bulk collect into enames limit cn_batch_size;
for i in
1..enames.count loop
dbms_output.put_line(enames(i));
endloop;
exit
when enames.count < cn_batch_size;
endloop;
close cur_emp;
end;
參考
不用繫結變數的寫法:
string empno = '7369';
string query_sql = 'select ename from t_emp where empno = 7369 ';
stmt = con.preparestatement( query_sql );
stmt.executequery();
使用繫結變數的寫法:
string empno = '***xx';
string query_sql = 'select ename from t_emp where empno = ? '; //嵌入繫結變數
stmt = con.preparestatement( query_sql );
stmt.setstring(1, empno ); //為繫結變數賦值
stmt.executequery();
批量繫結變數寫法: 此例子來自
string vc_sql = 'update t_emp set sal = ? where empno = ?';
pstmt = connection.preparestatement(dml);
pstmt.clearbatch();
for (int i = 0; i < update_count; ++ i)
pstmt.executebatch();
connection.commit();
SQL調優之繫結變數用法簡介
介紹繫結變數之前,先介紹sql執行過程和硬解析的概念 執行sql的過程,會將sql的文字進行hash運算,得到物件的hash值,然後拿hash值,去hash buckets裡遍歷快取物件控制代碼鍊錶,找到對應的快取物件控制代碼,然後就可以得到快取物件控制代碼裡對應sql執行計畫 解析樹等物件,所以執...
SQL調優之繫結變數用法簡介
介紹繫結變數之前,先介紹sql執行過程和硬解析的概念 執行sql的過程,會將sql的文字進行hash運算,得到物件的hash值,然後拿hash值,去hash buckets裡遍歷快取物件控制代碼鍊錶,找到對應的快取物件控制代碼,然後就可以得到快取物件控制代碼裡對應sql執行計畫 解析樹等物件,所以執...
SQL調優之繫結變數用法簡介
介紹繫結變數之前,先介紹sql執行過程和硬解析的概念 執行sql的過程,會將sql的文字進行hash運算,得到物件的hash值,然後拿hash值,去hash buckets裡遍歷快取物件控制代碼鍊錶,找到對應的快取物件控制代碼,然後就可以得到快取物件控制代碼裡對應sql執行計畫 解析樹等物件,所以執...