ORACLE使用WITH AS和HINT MATERIALIZE优化SQL解决FILTER效率低下
在做项目的过程中,一个页面使用类似例如以下的SQL查询数据。为了保密和使用方便,我把项目中有关的表名和字段替换使用ORACLE数据库中的系统表和字段。
在我所做的项目中。类似ALL_TABLES的表中大概有8W多条数据,以下这个查询SQL非常慢。
WITH PARAMS AS
(SELECT '' USER_ID, '' SDATE, '%' || '' || '%' SNAME FROM DUAL)
SELECT AU.USERNAME, AU.USER_ID
FROM ALL_USERS AU
INNER JOIN PARAMS PA
ON 1 = 1
INNER JOIN DBA_USERS DU
ON AU.USERNAME = DU.USERNAME
WHERE ((PA.SDATE IS NULL AND PA.USER_ID IS NOT NULL AND
AU.USER_ID = PA.USER_ID) OR (PA.SDATE IS NULL AND PA.USER_ID IS NULL AND
AU.USERNAME NOT IN
(SELECT AU.USERNAME
FROM ALL_USERS AU
INNER JOIN DBA_USERS DEV
ON AU.USERNAME = DEV.USERNAME
INNER JOIN (SELECT OWNER AS USERNAME
FROM ALL_TABLES T
WHERE T.LAST_ANALYZED = TRUNC(SYSDATE)) ATA
ON AU.USERNAME = ATA.USERNAME)) OR
(PA.SDATE IS NOT NULL AND
AU.USERNAME IN
(SELECT AU.USERNAME
FROM ALL_USERS AU
INNER JOIN DBA_USERS PA
ON AU.USERNAME = PA.USERNAME
INNER JOIN ALL_TABLES ATA
ON PA.USERNAME = ATA.OWNER
WHERE TO_CHAR(ATA.LAST_ANALYZED, 'YYYY-MM-DD') = PA.SDATE) AND
AU.USER_ID = PA.USER_ID))
AND DU.PROFILE LIKE 'D%'
AND AU.USERNAME LIKE PA.SNAME
针对上面的SQL语句运行慢的问题。我做了例如以下的分析:
第一步,把语句的WHERE条件后的三个OR都分别和主查询一块运行,运行速度都非常快,放到一块就非常慢。
第二步。对照上面SQL和三个OR拆分出来的三个SQL的运行计划,例如以下图所看到的。发现上面SQL的运行中有一个FILTER,过滤器谓词中用到了NOT
EXISTS,是导致这条SQL跑的慢的原因。
原因找到了。就得想办法把运行计划的FILTER去掉。開始想加HINT。可是实验了非常多HINT。都不起作用。最后的结果还一样,后来想到WITH
AS 能提高SQL的查询速度,就把影响SQL运行的那段SQL放到WITH
AS里面,结果还是一样。后来尝试把HINT
MATERIALIZE和WITH AS
结合使用,改动成例如以下的SQL,查询速度马上提升了非常多。例如以下图所看到的。运行计划中FILTER的NOT
EXISTS不存在了。
WITH PARAMS AS
(SELECT '' USER_ID, '' SDATE, '%' || '' || '%' SNAME FROM DUAL),
USERNAMEDATA AS
(SELECT /*+ materialize */
AU.USERNAME
FROM ALL_USERS AU
INNER JOIN DBA_USERS DEV
ON AU.USERNAME = DEV.USERNAME
INNER JOIN (SELECT OWNER AS USERNAME
FROM ALL_TABLES T
WHERE T.LAST_ANALYZED = TRUNC(SYSDATE)) ATA
ON AU.USERNAME = ATA.USERNAME)
SELECT AU.USERNAME, AU.USER_ID
FROM ALL_USERS AU
INNER JOIN PARAMS PA
ON 1 = 1
INNER JOIN DBA_USERS DU
ON AU.USERNAME = DU.USERNAME
WHERE ((PA.SDATE IS NULL AND PA.USER_ID IS NOT NULL AND
AU.USER_ID = PA.USER_ID) OR (PA.SDATE IS NULL AND PA.USER_ID IS NULL AND
AU.USERNAME NOT IN (SELECT USERNAME FROM USERNAMEDATA)) OR
(PA.SDATE IS NOT NULL AND
AU.USERNAME IN
(SELECT AU.USERNAME
FROM ALL_USERS AU
INNER JOIN DBA_USERS PA
ON AU.USERNAME = PA.USERNAME
INNER JOIN ALL_TABLES ATA
ON PA.USERNAME = ATA.OWNER
WHERE TO_CHAR(ATA.LAST_ANALYZED, 'YYYY-MM-DD') = PA.SDATE) AND
AU.USER_ID = PA.USER_ID))
AND DU.PROFILE LIKE 'D%'
AND AU.USERNAME LIKE PA.SNAME
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGlhbmd3ZWl3ZWkxMzA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
总结:
在FILTER中。NOT EXISTS后的SQL语句多次运行,本来数据量就非常大,每次都要运行一遍,结果可想而知。可是使用HINT
MATERIALIZE和WITH AS
结合使用,把内联视图实体化,运行过程中会创建基于视图的暂时表。
这样就不会每次NOT EXISTS都去运行一遍大数据表的扫描,仅仅须要扫描一次就可以。
可是是不是能够在WITHAS中的每一个语句都实体化那?假设WITH
AS中的语句仅仅被调用一次的话,不妨不要使用HINT
MATERIALIZE。由于使用HINT
MATERIALIZE第一次查询会创建基于视图结果的暂时表,这也耗费一些时间。
多次使用的话能够使用HINT
MATERIALIZE。
ORACLE使用WITH AS和HINT MATERIALIZE优化SQL解决FILTER效率低下的更多相关文章
- 简述项目中优化sql语句执行效率的方法,从哪些方面,sql语句性能如何分析?
(1)尽量选择较小的列: (2)将where中用的比较频繁的字段建立索引: (3)select中避免使用*: (4)避免在索引列上使用计算.not in和<>等操作: (5)当只需要一行数 ...
- SQL优化系列(一)- 优化SQL
优化SQL SQL开发人员从源代码中发现一条跑得很慢的SQL, 如何优化? DBA从AWR报告中发现一条跑得很慢的SQL,没有源代码或者不想修改源代码怎么办? SQL自动优化工具SQL Tuning ...
- WITH+HInt MATERIALIZE 不见得有效
那个要多次调用才需要物化的. 只调用一次,物化没用 MATERIALIZE 语法:MATERIALIZE 描述:指示优化器将内联视图实体化————执行过程中会创建基于视图的临时表. with dd ...
- Oracle三组难缠的hint no_unnest/unnest,push_subq,push_pred--平展化(转)
经常有人把这三个hint搞混,主如果因为对三种重写道理不清楚.特总结如下.(实验景象为10204)1. no_unnest, unnestunnest我们称为对子查询展开,顾名思义,就是别让子查询孤单 ...
- Oracle 11g R2性能优化 SQL TRACE
作为Oracle官方自带的一种基本性能诊断工具,SQL Trace可以用来评估当前正在运行的SQL语句的效率,同时为该语句生成统计信息等,并保存这些信息到指定路径下的跟踪文件(trace)当中.SQL ...
- 如何用 SQL Tuning Advisor (STA) 优化SQL语句
在Oracle10g之前,优化SQL是个比较费力的技术活,不停的分析执行计划,加hint,分析统计信息等等.在10g中,Oracle推出了自己的SQL优化辅助工具: SQL优化器(SQL Tuning ...
- sql语句优化SQL Server
MS SQL Server查询优化方法查询速度慢的原因很多,常见如下几种 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了 ...
- paip.索引优化---sql distict—order by 法
paip.索引优化---sql distict—order by 法 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog ...
- 转载 50种方法优化SQL Server数据库查询
原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1 ...
随机推荐
- BZOJ一句话
一句话题解集合. 1061: [Noi2008]志愿者招募 单纯形,运用对偶原理转化过来,变成标准形然后单纯性裸上即可. #include<cmath> #include<cstdi ...
- visualvm监控tomcat
https://my.oschina.net/weidedong/blog/787203
- C语言利用 void 类型指针实现面向对象类概念与抽象
不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象. 不过多态和继承这种实现,就有点小麻烦,但是依然可以实现. 核心: ...
- jquery05 继承
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- c++笔试题:不使用第三个变量来交换俩个变量的数值
题目:将a 与 b的值互换. 通常我们的做法是(尤其是在学习阶段):定义一个新的变量,借助它完成交换.代码如下: int a,b; a; b: int t; t ...
- 面向对象(OO)基础
面向对象,英文Object-Oriented,简称OO),另外相关的还有:面向对象分析(Object-Oriented Analysis,OOA) 面向对象设计(Object-Oriented Des ...
- Kinect 开发 —— Hello,Kinect
控制台输出深度数据: using System; using System.Collections.Generic; using System.Linq; using System.Text; usi ...
- css3+jq--小箭头旋转180度案例
html: <aside class="tea_getBtn"> <div class="w"> <span class=&quo ...
- 03010_防止SQL注入
1.预处理对象 (1)使用PreparedStatement预处理对象时,建议每条sql语句所有的实际参数,都使用逗号分隔: String sql = "insert into sort(s ...
- 【习题 8-3 UVA - 12545】Bits Equalizer
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 如果1的个数第一个串比第2个串多. 那么就无解. 否则. 找几个位置去凑1 优先找'?'然后才是0的位置 剩余的全都用swap操作就 ...