19c优化器对left join含or关联的

本文讨论了在19c数据库版本升级后,如何通过改写SQL和创建索引来提高执行效率,特别是针对大表的Hashjoin使用。作者强调了优化SQL的重要性,而非单纯依赖硬件升级。

有下面类似SQL写法, 在19c之前, 只能使用Nested loops的执行计划, 如果T1表比较大, SQL执行效率会比较差.

下面SQL如果不在T2表的object_name字段上创建索引, 执行效率更是会差到无法接受.

升级到了19c版本后, 优化器做了一些改进, 上面的SQL可以使用hash join了, 如果T1表是大表, 执行效率会有明显的提高.

那么问题来了:

19c版本之前, 该做怎样的改写, 能让优化器使用Hash join的执行计划?

这个是有真实生产案例的, SQL执行时间长达40多分钟, 客户无奈只能接受(或者说忍受)这个时间, 把or条件用case when改写一下, 执行时间降到10分钟以下, 确实是让大家都挺开心的一件事.

一个业务SQL需要访问多少数据量和执行时间是有一个预期的, 超出了这个预期, 都在优化范围.

现在的生产系统, 大家都把性能提升寄希望于硬件的改善, 这种思想是不好的, 基本上大部分Top SQL都是需要优化而且是可以优化的.

create table t1 as select *from dba_objects;

create table t2 as select *from t1;
insert into t2 select *from t1;
create index t2_idx on t2(object_name)

select count(*) from t1;
select count(*) from t2;
select count(*) from t1 x where x.owner='SYS'

select count(*) from (
select /*+ no_use_hash(x,t2)*/x.owner t1,x.* from t1 x left join t2 on x.object_name=t2.object_name
and (x.object_id=t2.object_id  or  x.object_id=t2.data_object_id) 
and x.owner='SYS'
)
 where  t1='SYS'
 
 select /*+ no_use_hash(x,t2)*/count(*) from t1 x left join t2 on x.object_name=t2.object_name
and (x.object_id=t2.object_id  or  x.object_id=t2.data_object_id) 
 and x.owner='SYS'
 
  select /*+ no_use_hash(x,t2)*/count(*) from t1 x left join t2 on x.object_name=t2.object_name
and (x.object_id=t2.object_id  or  x.object_id=t2.data_object_id) 
 where  x.owner='SYS'


 
select count(*) from t1 x ,t2 where  x.object_name=t2.object_name(+)
and (x.object_id=t2.object_id(+)  or  x.object_id=t2.data_object_id(+)) 
and x.owner='SYS'

ORA-01719: outer join operator (+) not allowed in operand of OR or IN


select count(*) from t1 x ,t2 where  x.object_name=t2.object_name(+)
and x.object_id=t2.object_id(+)   
and x.owner='SYS' --422265

select count(*)  from t1 x left join t2 on x.object_name=t2.object_name
and (x.object_id=t2.object_id  ) 
and x.owner='SYS'--442762 --and 的意思T1表全部要,但只用SYS的数据去join

select count(*)  from t1 x left join t2 on x.object_name=t2.object_name
and (x.object_id=t2.object_id  ) 
where  x.owner='SYS'--422265-----where 才是过滤T1的


select count(*) from (
select * from t1 x left join t2 on x.object_name=t2.object_name
and (x.object_id=t2.object_id  ) 
and x.owner='SYS'
union 
select * from t1 x left join t2 on x.object_name=t2.object_name
and (x.object_id=t2.data_object_id  ) 
and x.owner='SYS')

SELECT df.tablespace_name AS "表空间名", df.total_space AS "总空间(MB)", NVL(fs.free_space, 0) AS "空闲空间(MB)", (df.total_space - NVL(fs.free_space, 0)) AS "已用空间(MB)", ROUND((df.total_space - NVL(fs.free_space, 0)) 2 3 4 5 6 * 100 / df.total_space, 2) AS "利用率(%)" FROM (SELECT tablespace_name, ROUND(SUM(bytes) / 1024 / 1024, 2) total_space FROM dba_data_files GROUP BY tablespace_name) df LEFT JOIN (SELECT 7 8 9 10 11 12 13 14 15 16 17 tablespace_name, ROUND(SUM(bytes) / 1024 / 1024, 2) free_space FROM dba_free_space GROUP BY tablespace_name) fs ON df.tablespace_name = fs.tablespace_name ORDER BY "利用率(%)" DESC; 18 19 20 21 22 23 24 25 26 表空间名 总空间(MB) 空闲空间(MB) 已用空间(MB) 利用率(%) ------------------------------ ---------- ------------ ------------ ---------- SYSTEM 65527.98 117.94 65410.04 99.82 TIMP_XZEEMS_INTER_FLOW 20992 1237.13 19754.87 94.11 SYSAUX 1800 116.94 1683.06 93.5 TIMP_XZEEMS_INTRA_FLOW 8192 768.69 7423.31 90.62 USERS 5 3.69 1.31 26.2 UNDOTBS1 175 137.94 37.06 21.18 TIMP_XZEEMS_INTRA 1024 985.31 38.69 3.78 TIMP_XZEEMS_INTER 1024 986.13 37.87 3.7 TIMP_XZEEMS_MQ_INTRA 1024 1019.63 4.37 .43 9 rows selected. SQL> SELECT a.tablespace_name AS "表空间名", ROUND(a.bytes_alloc / 1024 / 1024, 2) AS "总空间(MB)", ROUND((a.bytes_alloc - NVL(b.bytes_free, 0)) / 1024 / 1024, 2) AS "已用空间(MB)", ROUND(NVL(b.bytes_free, 0) / 1024 / 1024, 2) AS "空 2 3 4 5 闲空间(MB)", ROUND((a.bytes_alloc - NVL(b.bytes_free, 0)) / a.bytes_alloc * 100, 2) AS "利用率(%)", a.autoextensible AS "自动扩展" FROM (SELECT tablespace_name, SUM(bytes) bytes_alloc, MAX(autoextensible) aut 6 7 8 9 10 11 12 oextensible FROM dba_data_files GROUP BY tablespace_name) a LEFT JOIN (SELECT tablespace_name, SUM(bytes) bytes_free FROM dba_free_space GROUP BY tablespace_name) b ON a.tablespace_name = b.tablespace_name UNION AL 13 14 15 16 17 18 19 20 21 22 L SELECT tablespace_name AS "表空间名", ROUND(SUM(bytes) / 1024 / 1024, 2) AS "总空间(MB)", ROUND(SUM(bytes_used) / 1024 / 1024, 2) AS "已用空间(MB)", ROUND(SUM(bytes_free) / 1024 / 1024, 2) AS "空闲空间(MB)", ROUND(SUM( 23 24 25 26 27 28 bytes_used) / SUM(bytes) * 100, 2) AS "利用率(%)", 'YES' AS "自动扩展" FROM dba_temp_free_space GROUP BY tablespace_name ORDER BY 5 DESC; 29 30 31 32 ROUND(SUM(bytes_used) / SUM(bytes) * 100, 2) AS "利用率(%)", * ERROR at line 28: ORA-00904: "BYTES": invalid identifier
08-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值