演示确定共享池中是否存在未绑定变量的 SQL
本文内容
- remove_constants 函数
- 测试环境
- 测试共享池中是否存在绑定变量的 SQL
remove_constants 函数
确定系统中是否存在绑定变量的情况,ASKTOM 网站提供了一个 remove_constants 函数,以检查共享池中 SQL 的运行情况。
SQL> CREATE OR REPLACE FUNCTION remove_constants (p_query IN VARCHAR2)
2 RETURN VARCHAR2
3 AS
4 l_query LONG;
5 l_char VARCHAR2 (2);
6 l_in_quotes BOOLEAN DEFAULT FALSE;
7 BEGIN
8 FOR i IN 1 .. LENGTH (p_query)
9 LOOP
10 l_char := SUBSTR (p_query, i, 1);
11
12 IF l_char = '''' AND l_in_quotes
13 THEN
14 l_in_quotes := FALSE;
15 ELSIF l_char = '''' AND NOT l_in_quotes
16 THEN
17 l_in_quotes := TRUE;
18 l_query := l_query || '''#';
19 END IF;
20
21 IF NOT l_in_quotes
22 THEN
23 l_query := l_query || l_char;
24 END IF;
25 END LOOP;
26
27 l_query := TRANSLATE (l_query, '0123456789', '@@@@@@@@@@');
28
29 FOR i IN 0 .. 8
30 LOOP
31 l_query := REPLACE (l_query, LPAD ('@', 10 - i, '@'), '@');
32 l_query := REPLACE (l_query, LPAD (' ', 10 - i, ' '), ' ');
33 END LOOP;
34
35 RETURN UPPER (l_query);
36 END;
37 /
函数已创建。
SQL>
测试环境
创建表 t,并创建匿名存储过程,执行不绑定变量的 SQL 1000 次。
SQL> create table t(id int);
表已创建。
SQL> BEGIN
2 FOR i IN 1 .. 1000
3 LOOP
4 EXECUTE IMMEDIATE 'select * from t where id=' || i;
5 END LOOP;
6 END;
7 /
PL/SQL 过程已成功完成。
SQL>
测试共享池中是否存在绑定变量的 SQL
利用 v$sqlarea 视图创建表 t1,并调用 remove_constants 进行整理。
SQL> create table t1 as select sql_text from v$sqlarea;
表已创建。
SQL> alter table t1 add sql_text_wo_constants varchar2(1000);
表已更改。
SQL> UPDATE t1
2 SET sql_text_wo_constants = remove_constants (sql_text);
已更新3474行。
SQL> SELECT sql_text_wo_constants, COUNT (*)
2 FROM t1
3 GROUP BY sql_text_wo_constants
4 HAVING COUNT (*) > 100
5 ORDER BY 2;
SQL_TEXT_WO_CONSTANTS COUNT(*)
-------------------------------------------------- ----------
SELECT * FROM T WHERE ID=@ 1000
SQL>
从结果中,刚才执行的 select 语句被反复分析 1000 次,其中谓词条件用 @ 代替。如果绑定了变量,顶多一次。这样,通过这个函数,可以很容易地找到共享池中哪些 SQL 没有绑定变量。