8.3.1 数据环境准备
drop table test1;
drop table test2;
drop table test3;
create table test1 as select * from dba_objects;
create table test2 as select * from test1;
create table test3 as select * from test1;
insert into test2 select * from test2;
insert into test2 select * from test2;
insert into test3 select * from test3;
insert into test3 select * from test3;
create index ix_test1_01 on test1(object_id);
create index ix_test2_01 on test2(object_id,DATA_OBJECT_ID,OWNER,OBJECT_NAME);
create index ix_test3_01 on test3(object_id,DATA_OBJECT_ID,OWNER,OBJECT_NAME);
8.3.2 问题SQL
SELECT COUNT(*)
FROM TEST2 T2
WHERE T2.OBJECT_ID IN (SELECT T3.OBJECT_ID
FROM TEST3 T3
WHERE T3.DATA_OBJECT_ID<3000)
OR T2.OWNER IN (SELECT T3.OWNER
FROM TEST3 T3
WHERE T3.OBJECT_NAME='V$SQL_PLAN')
OR T2.DATA_OBJECT_ID IN (SELECT T3.DATA_OBJECT_ID
FROM TEST3 T3
WHERE T3.OBJECT_ID<3000);
8.3.3 SQL优化改写1
SELECT COUNT(*) FROM
(SELECT *
FROM TEST2 T2
WHERE T2.OBJECT_ID IN (SELECT T3.OBJECT_ID
FROM TEST3 T3
WHERE T3.DATA_OBJECT_ID<3000)
UNION
SELECT *
FROM TEST2 T2
WHERE T2.OWNER IN (SELECT T3.OWNER
FROM TEST3 T3
WHERE T3.OBJECT_NAME='V$SQL_PLAN')
UNION
SELECT *
FROM TEST2 T2
WHERE T2.DATA_OBJECT_ID IN (SELECT T3.DATA_OBJECT_ID
FROM TEST3 T3
WHERE T3.OBJECT_ID<3000));
性能反而下降了,主要原因是id 11,12用owner进行关联时,走了内连接,没走半连接,重复值太多,造成数据翻翻。
这里优化器改为内连接的原因是union有去重复的作用。
8.3.4 SQL优化改写2
SELECT COUNT(*) FROM (
SELECT DISTINCT TT.* FROM
(SELECT *
FROM TEST2 T2
WHERE T2.OBJECT_ID IN (SELECT T3.OBJECT_ID
FROM TEST3 T3
WHERE T3.DATA_OBJECT_ID<3000)
UNION ALL
SELECT *
FROM TEST2 T2
WHERE T2.OWNER IN (SELECT T3.OWNER
FROM TEST3 T3
WHERE T3.OBJECT_NAME='V$SQL_PLAN')
UNION ALL
SELECT *
FROM TEST2 T2
WHERE T2.DATA_OBJECT_ID IN (SELECT T3.DATA_OBJECT_ID
FROM TEST3 T3
WHERE T3.OBJECT_ID<3000)) TT);
虽然看着成本增加了,但是执行时间由100多秒下降到不到2秒。