96 - or exists写法分析与优化方法
偶然看到一个国产数据库的SQL优化介绍:
下面分析一下这两种写法的优劣:
原or exists写法(写法1):
如果test表结果集小(不含or条件), 那么最终返回的结果集也小,如果test_bak表的object_id字段上有索引, 这种情况是不需要改写的. 如果test_bak表比较大, 改写后反而性能会变差(可能没有merge和push_pred这些查询转换, 大表test_bak要先全表扫描去重, 这个消耗是比较大的).
上面left join改写(写法2)比较适合的场景是:
test表结果集大, test_bak结果集大, 最终结果集也大的情况, 两表可以做hash join, 避免主表做大量filter操作导致性能很差.
上面的改写还漏掉了一个比较重要而且常见的情况, 那就是test表结果集大, 最终结果集小的场景, 这个场景在OLTP系统也是比较常见的, 这种情况改成union all是最佳的(写法3):
select * from test where owner='SCOTT'
union all
select * from test where exists
(select 1 from test_bak where test.object_id=test_bak.object_id)
and lnnvl(owner='SCOTT');
需要特别注意的是: 是用union all改写, 不是union.
回到oracle数据库, 在版本12.2 前, 也要根据上面规则做对应的改写;
在12.2及以上版本,如果写法1效率差, 而且数据分布符合写法3 , 可以不需要改写, 而是通过or_expand的hint让优化器根据指示, 做出查询转换变成写法3; 如果数据分布符合写法2, 还是需要手动改写.
OLTP系统返回一般返回的结果集小, 写法1和写法3 总有一个是适用的 , 而且hint是可以应用到某个具体SQL的. 所以在12.2之后, 不太复杂的 or exists 基本上就不存在性能问题了. 如果是复杂的or exists , 那就要根据情况见招拆招了.
文中观点仅代表本人, 如有不妥, 请指正, 感谢!
全文完
相关文章
- 【愚公系列】2023年01月 .NET/C#知识点-List对象去重的方法总结
- 【Android 性能优化】应用启动优化 ( 安卓应用启动分析 | Launcher 应用简介 | Launcher 应用源码简介 | Launcher 应用快捷方式图标点击方法分析 )
- 干涉MySQL优化器使用hash join的方法
- Oracle 等待事件 log file single write 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 PX signal server 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 Redo Writer Remote Sync Complete 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 Enqueues:DF,Datafile 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 Enqueues:DR,DistributedRecoveryProcess 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 Enqueues:SN,SequenceNumber 官方解释,作用,如何使用及优化方法
- Oracle 等待事件 Enqueues:SS,SortSegment 官方解释,作用,如何使用及优化方法
- 深入浅出:基于Oracle的表格创建方法(oracle如何创建表)
- 一种自动化检测 Flash 中 XSS 方法的探讨
- Oracle加减函数简介及使用方法(oracle加减函数)
- 深入分析Linux Top指令,优化系统性能的方法与技巧(分析linux top)
- Oracle事务日志清理一种优化数据库性能的方法(oracle事物日志清理)
- MySQL 索引优化海量数据上亿行的索引建立方法(mysql上亿行建索引)
- javascript数组的方法集合
- php运行出现Calltoundefinedfunctioncurl_init()的解决方法
- PHPUnitPHP测试框架安装方法
- 深入C#内存管理以及优化的方法详解
- java计算自然数中的水仙花数的方法分享