1. 来看NOT NULL约束如何影响执行计划:
code1: 创建数据隔离的表和视图
drop table t1;
drop table t2;
drop view v;
create table t1
as
select * from all_objects
where object_type in (‘TABLE‘,‘VIEW‘);
alter table t1 modify object_type not null;
alter table t1 add constraint t1_check_otype check (object_type in(‘TABLE‘,‘VIEW‘));
create table t2
as
select * from all_objects
where object_type in ( ‘SYNONYM‘, ‘PROCEDURE‘ );
alter table t2 modify object_type not null;
alter table t2 add constraint t2_check_otype
check (object_type in (‘SYNONYM‘, ‘PROCEDURE‘));
create or replace view v
as
select * from t1
union all
select * from t2;
code2: 优化掉一个表
set autotrace traceonly explain
select * from v where object_type = ‘TABLE‘;
Execution Plan
----------------------------------------------------------------------------
Plan hash value: 3982894595
这个计划没有使用我们创建的索引。原因是object_type列是nullable,索引并不包含所有NULL值,所以无法根据索引键值进行
COUNT操作。如果我们告诉数据库:OBJECT_TYPE IS NOT NULL,执行计划将立马转变!
code4:
alter table t modify object_type NOT NULL;
select count(*) from t;
Execution Plan
------------------------------------------
Plan hash value: 1058879072
------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 54 (2)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FAST FULL SCAN| T_IDX | 68437 | 54 (2)| 00:00:01 |
------------------------------------------------------------------------
some kind of 神奇吧!
问题是加入该object_type列可以为NULL,又该如何解决?答案是我们可以创建多列索引(组合索引)当然object_type比在其中。
例如:
code5:
drop index t_idx;
create index t_idx on t (object_type, 0);
code6:
select * from t where object_type is null;
Execution Plan
-----------------------------
Plan hash value: 470836197
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 101 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID | T | 1 | 101 | 1 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 1 | | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_TYPE" IS NULL)
2、来看主外键约束如何影响执行计划:
code7:
drop table emp;
drop table dept;
drop view emp_dept;
create table emp
as
select *
from scott.emp;
create table dept
as
select *
from scott.dept;
create or replace view emp_dept
as
select emp.ename, dept.dname
from emp, dept
where emp.deptno = dept.deptno;
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("EMP"."DEPTNO" IS NOT NULL)
起作用了!加了个filter。
3、来看一个NOT NULL和主外键约束搭配物化视图查询是如何影响执行计划的
我经常把物化视图作为”数据仓库索引“使用,其最重要的用途是作为“preanswer”,将针对特定表的复杂和长时间运行的结果保存在一个永久表中。
说白了就是加速查询速度。
alter table emp drop constraint emp_fk_dept;
alter table dept drop constraint dept_pk;
code10:
create materialized view mv enable query rewrite
as
select dept.deptno, dept.dname, count (*) from emp, dept
where emp.deptno = dept.deptno
group by dept.deptno, dept.dname;
begin
dbms_stats.set_table_stats
( user, ‘MV‘, numrows=>100000, numblks=>10000 );
end;
/
code11: 一个查询使用物化视图
select dept.dname, count (*) from emp, dept
where emp.deptno = dept.deptno and dept.dname = ‘SALES‘
group by dept.dname;
Execution Plan
------------------------------
Plan hash value: 1703036361