blogofdee 2019-03-26
如何快速判断 SOL 执行计划是否高效,其实这是一个知识和经验的完美结合过程。其实也有一些维度可以作为参考的,下面一起来看看吧。
DROP TABLE t; CREATE TABLE t as select * from dba_objects; --CREATE INDEX idx ON t (object_id); alter session set statistics_level=all; set linesize 200 set pagesize 200 select * from t where object_id=6; SELECT * FROM table(dbms_xplan.display_cursor(NULL,NULL,'allstats last'));
说明:总共获取 1 条记录(A-ROWS),产生 1249 次逻辑读( Buffers),这里很明显就有问题了。
1、创建测试数据
DROP TABLE t1; CREATE TABLE t1 (id, col1, col2, pad) AS SELECT rownum, CASE WHEN rownum>5000 THEN 666 ELSE rownum END,rownum, lpad('*',100,'*') FROM dual CONNECT BY level <= 10000; INSERT INTO t1 SELECT id+10000, col1, col2, pad FROM t1; INSERT INTO t1 SELECT id+20000, col1, col2, pad FROM t1; INSERT INTO t1 SELECT id+40000, col1, col2, pad FROM t1; INSERT INTO t1 SELECT id+80000, col1, col2, pad FROM t1; COMMIT; CREATE INDEX t1_col1 ON t1 (col1); DROP TABLE t2; CREATE TABLE t2 AS SELECT * FROM t1 WHERE mod(col2,19) != 0; ALTER TABLE t2 ADD CONSTRAINT t2_pk PRIMARY KEY (id);
2、统计分析,但是不搜集直方图
BEGIN dbms_stats.gather_table_stats( ownname=>user, tabname=>'T1', cascade=>TRUE, estimate_percent=>100, method_opt=>'for all columns size 1', no_invalidate=>FALSE); END; / BEGIN dbms_stats.gather_table_stats( ownname=>user, tabname=>'T2', cascade=>TRUE, estimate_percent=>100, method_opt=>'for all columns size 1', no_invalidate=>FALSE); END; /
3、评估值是否准确
set linesize 200 set pagesize 200 explain plan for SELECT count(t2.col2) FROM t1 ,t2 WHERE t1.id=t2.id and t1.col1 = 666; select * from table(dbms_xplan.display());
SELECT /*+ gather__plan_statistics */ count(t2.col2) FROM t1, t2 WHERE t1.id=t2.id and t1.col1 = 666; select * from table(dbms_xplan.display_cursor(NULL,NULL,'allstats last'));
drop table t_col_type purge; create table t_col_type(id varchar2(20),col2 varchar2(20),col3 varchar2(20)); insert into t_col_type select rownum,'abc','efg' from dual connect by level<=10000; commit; create index idx_id on t_col_type(id); set linesize 200 set autotrace traceonly select * from t_col_type where id=6;
如果是filter一般就是走全扫了,access是索引扫
1、创建测试数据
set autotrace off; drop table people purge; create table people (first_name varchar2(200),last_name varchar2(200),sex_id number); create table sex(name varchar2(20), sex_id number); insert into people (first_name,last_name,sex_id) select object_name,object_type,1 from dba_objects; insert into sex(name,sex_id) values('男',1); insert into sex(name,sex_id) values('女',2); insert into sex(name,sex_id) values ('不详',3); commit;
2、创建函数
create or replace function get_sex_name(p_id sex.sex_id%type) return sex.name%type is v_name sex.name%type; begin select name into v_name from sex where sex_id=p_id; return v_name; end; /
3、查看递归调用
set autotrace traceonly select sex_id,first_name||' '||last_name full_name,get_sex_name(sex_id) gender from people;
1、创建测试数据
DROP TABLE t1; CREATE TABLE t1 (id, col1, col2, pad) AS SELECT rownum, CASE WHEN rownum>5000 THEN 666 ELSE rownum END, rownum, lpad('*',100,'*') FROM dual CONNECT BY level <= 10000; INSERT INTO t1 SELECT id+10000, col1, col2, pad FROM t1; INSERT INTO t1 SELECT id+20000, col1, col2, pad FROM t1; INSERT INTO t1 SELECT id+40000, col1, col2, pad FROM t1; INSERT INTO t1 SELECT id+80000, col1, col2, pad FROM t1; COMMIT; CREATE INDEX t1_col1 ON t1 (col1); DROP TABLE t2; CREATE TABLE t2 AS SELECT * FROM t1 WHERE mod(col2,19) != 0; ALTER TABLE t2 ADD CONSTRAINT t2_pk PRIMARY KEY (id);
2、统计分析,但是不搜集直方图
BEGIN dbms_stats.gather_table_stats( ownname=>user, tabname=>'T1', cascade=>TRUE, estimate_percent=>100, method_opt=>'for all columns size 1', no_invalidate=>FALSE); END; / BEGIN dbms_stats.gather_table_stats( ownname=>user, tabname=>'T2', cascade=>TRUE, estimate_percent=>100, method_opt=>'for all columns size 1', no_invalidate=>FALSE); END; /
3、查看表访问次数
alter session set statistics_level=all; SELECT /*+ gather_plan_statistics */ count(t2.col2) FROM t1 ,t2 WHERE t1.id=t2.id and t1.col1 = 666; SELECT * FROM table(dbms_xplan.display_cursor(NULL,NULL,'allstats last'));
drop table t1 cascade constraints; create table t1 as select * from dba_objects; drop table t2 cascade constraints; create table t2 (id1,id2) as select rownum ,rownum+100 from dual connect by level <=1000; set autotrace traceonly; select * from (select t1.*, rownum as rn from t1, t2 where t1.object_id = t2.id1) a where a.rn >= 1 and a.rn <= 10; select * from (select t1.*, rownum as rn from t1, t2 where t1.object_id = t2.id1 and rownum<=10 ) a where a.rn >= 1;
drop table t purge; create table t as select * from dba_objects; set autotrace traceonly select * from t where object_id>2 order by object_id;
上面是几个维度判断执行计划中sql的效率,实际上还有一个计算方式是通过consistent gets来计算内存大致使用多少,通过physical reads来计算IO。
后面会分享更多关于DBA方面内容,感兴趣的朋友可以关注下!!