8
DBA应对未使用绑定变量的方法1 前期预防 (上策)
在项目开发初期 对程序员进行培训与指导
1 引入后台开发程序员 尽量将SQL语句放入后台包(PACKAGE)中。
这样的好处:
省资源: 省去了网络传输语句的消耗。应用服务器只要传输接口与结果集即可。不需要传送SQL文本
分工明确:前台程序只是用于界面的转发。
后台程序负责数据的提取与变更。
前后台的程序员都只需要关心一个层面。久而久之开发技能更加专业。一般来说一个后台程序员可以配合三至五个前台开发程序员进行开发。
开发效率高:分别用专业的工具进行前台,后台开发。开发效率高。
如 ECLIPSE 的工作界面就非常适合JAVA而不适合PL/SQL
PL/SQLDEVELOPER 只能进行后台开发。
但是这两种工具在其领域内都非常的专业,高效
2 后期挽救
1 对尚在开发期的程序 建议重新开发 (中策)
2 调整数据库参数cursor_sharing与使用存储纲要 (下策)
CURSOR_SHARING参数介绍
CURSOR_SHARING 定义了SQL共享的程度
EXACT:
SQL文本完全相同,并且所操作的对象也相同时 共享游标
SIMILAR
文本不同,并且不因为文本不同而影响了语句的含义或者优化的维度。
即如果条件列上使用了直方图,则使用硬解析。反之使用软解析。
FORCE
除非文本不同改变了语句的含义,否则强制使用游标共享。
2 存储纲要
数据倾斜情况下直方图的使用Oracle分析是默认为列的不同值的行数是相同的。所以在数据倾斜的情况下,就会给出错误的执行计划。而使用直方图,就是避免这种情况。优化器在解析sql语句生成执行计划的时候会考虑到直方图的统计信息。
但是过度使用直方图也是不好的。它增加了表,索引的分析时间。也增加了执行计划的生成时间。
只有在数据倾斜的情况下,才使用直方图。
SQL> create table test_for_col
as select rownum a,rownum b from dualconnect by level<=20000 ; SQL> update test_for_col set a=20000 where a between10 and 20000 ; SQL> create index idx_test on test_for_col(a); SQL> analyze table
test_for_col compute statistics; SQL> analyze index idx_test compute statistics ; SQL>
setautotrace trace exp ; SQL>
select *from test_for_col where a= 1 ; ---------------------------------------------------------- Planhash value: 3390667667 -------------------------------------------------------------------------------------------- |Id
| Operation
| Name
| Rows
| Bytes | Cost (%CPU)| Time
| -------------------------------------------------------------------------------------------- |
0 | SELECT STATEMENT
|
|
2000 | 12000 |
8
(0)| 00:00:01 | |
1 |
TABLE ACCESS BY INDEX ROWID| TEST_FOR_COL |
2000 | 12000 |
8
(0)| 00:00:01 | |*
2 |
INDEX RANGE SCAN
|IDX_TEST
|
2000 |
|
4
(0)| 00:00:01 | -------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- SQL> select * from test_for_col where a= 20000 ; ---------------------------------------------------------- Plan hash value: 3390667667 -------------------------------------------------------------------------------------------- | Id
|Operation
| Name
| Rows
| Bytes | Cost (%CPU)| Time
| -------------------------------------------------------------------------------------------- |
0 | SELECTSTATEMENT
|
|
2000 | 12000 |
8
(0)| 00:00:01 | |
1 |
TABLE ACCESS BY INDEX ROWID| TEST_FOR_COL|
2000 | 12000 |
8
(0)| 00:00:01 | |*
2 |
INDEX RANGE SCAN
| IDX_TEST
|
2000 |
|
4
(0)| 00:00:01 | -------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- SQL> select a,count(*) from test_for_col group by aorder by a ;
可以看出数据极度倾斜,并且在访问的时候给出了错误的执行计划。
现在修改分析命令构造直方图
SQL>
analyzetable
test_for_col compute statisticsfor all indexed
columns ; 这句命令的意思是
统计这个表所有索引列的信息。并构造直方图 SQL> select num_rows, blocks, empty_blocks, avg_space,chain_cnt, avg_row_len AND TABLE_NAME = UPPER('test_for_col')
2
3
4
;
NUM_ROWS
BLOCKS EMPTY_BLOCKS
AVG_SPACE
CHAIN_CNT AVG_ROW_LEN
---------- ---------- ------------ ---------- --------------------- SQL> select num_distinct, low_value, high_value,density, num_buckets, last_analyzed, sample_size
wheretable_name = UPPER('test_for_col') ;
2
3
NUM_DISTINCT LOW_VALUE
HIGH_VALUE
DENSITY NUM_BUCKETS LAST_ANALYZESAMPLE_SIZE ------------ -------------------------------------------- ----------- ------------ -----------
10C102
C303
.000025
10 13-OCT-09
20000
20000C102
C303
.00005
1 13-OCT-09
20000
SAMPLE_SIZE
采样的数量
可以使用SAMPLE子句来指定采样的百分比或者行数
重复刚才的实验
SQL> select * from test_for_col where a= 1 ;
----------------------------------------------------------
Plan hash value: 3390667667
-------------------------------------------------------------------------------------------- | Id
|Operation
| Name
| Rows
| Bytes | Cost (%CPU)| Time
| -------------------------------------------------------------------------------------------- |
0 | SELECTSTATEMENT
|
|
1 |
6 |
2
(0)| 00:00:01 | |
1 |
TABLE ACCESS BY INDEX ROWID| TEST_FOR_COL|
1 |
6 |
2
(0)| 00:00:01 | |*
2 |
INDEX RANGE SCAN
| IDX_TEST
|
1 |
|
1
(0)| 00:00:01 | -------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
---------------------------------------------------
SQL> select * from test_for_col where a= 20000 ;
----------------------------------------------------------
Plan hash value: 170577590
----------------------------------------------------------------------------------
| Id
|Operation
| Name
| Rows
| Bytes | Cost (%CPU)| Time
|
----------------------------------------------------------------------------------
|
0 | SELECTSTATEMENT
|
| 19991 |
117K|
11
(10)| 00:00:01 |
|*
1 |
TABLE ACCESS FULL| TEST_FOR_COL | 19991|
117K|
11
(10)| 00:00:01 |
----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
查看直方图内容
SQL>
selecttable_name, column_name, endpoint_number, endpoint_value
wheretable_name =
UPPER('test_for_col');
TABLE_NAME
COLUMN_NAM ENDPOINT_NUMBER ENDPOINT_VALUE -------------------- ---------- ----------------------------- TEST_FOR_COL
A
20000
20000 TABLE_NAME
COLUMN_NAM ENDPOINT_NUMBER ENDPOINT_VALUE -------------------- ---------- -----------------------------
直方图中的ENDPOINT_VALUE表示列值,ENDPOINT_NUMBER表示累积的行数。
TEST_FOR_COL
A
9
9
TEST_FOR_COL
A
20000
20000
表示A列值为20000的数据有20000-9=199991行。 |