SQL調優之繫結變數用法簡介

2021-09-27 07:28:51 字數 4769 閱讀 5142

介紹繫結變數之前,先介紹sql執行過程和硬解析的概念:

執行sql的過程,會將sql的文字進行hash運算,得到物件的hash值,然後拿hash值,去hash buckets裡遍歷快取物件控制代碼鍊錶,找到對應的快取物件控制代碼,然後就可以得到快取物件控制代碼裡對應sql執行計畫、解析樹等物件,所以執行相同的sql第二次執行時是會比較快的,因為不需要解析獲取執行計畫,解析樹等物件,如果找不到庫快取物件控制代碼,就需要重新解析,這個過程解析過多,容易造成硬解析問題

硬解析:是指oracle在執行目標sql時,在庫快取中找不到可以重用的解析樹和執行計畫,而不得不從頭開始解析目標sql並生成相應的parent cursor和child cursor的過程。

軟解析:是指oracle在執行目標sql時,在library cache中找到了匹配的parent cursor和child cursor,並將儲存在child cursor中的解析樹和執行計畫直接拿過來重用,無須從頭開始解析的過程。

ok,上面是sql執行過程的簡單介紹,由此可知,假如sql執行過程,在共享池裡找不到執行計畫、解析樹等就會重現解析sql,生成執行計畫和解析樹等,這個過程是比較耗時間的,所以要想辦法盡量不要重現解析sql,需要執行計畫直接去共享池拿已經生成的

舉個例子,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執行計畫 解析樹等物件,所以執...