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 ...
随机推荐
- 【Docker入门】
目录 Linux容器 Docker的优势 Docker三大概念 安装使用Docker 补充知识 [Docker入门] 发布文章 "qq_41964425" @ *** 所谓Dock ...
- Centos7.6下安装Python3.7
前言 话说不会开发的运维不是一个好的DBA,所以我要开始学习python了,写博客记录一下我的学习过程,另外别欺负我新来的,那个每天更博的技术流ken是我哥. 不说了,时间宝贵,开整. 1.首先来看一 ...
- 洛谷 P1913 L国的战斗之伞兵
P1913 L国的战斗之伞兵 题目背景 L国即将与I国发动战争!! 题目描述 为了在敌国渗透作战,指挥官决定:派出伞兵前往敌国!然而敌国的风十分强烈,能让伞兵在同一高度不停转悠,直到被刮到一个无风区… ...
- ArcGIS Engine 9.3启动程序报错
报错1: 没有注册类 (异常来自 HRESULT:0x80040154 解决办法: 由于是X64系统,将项目的生成目标该成X86就解决了. 报错2: 正试图在 OS 加载程序锁内执行托管代码.不要尝试 ...
- NumPy基础入门学习
对于习惯使用了MATLAB的用户而言,学习NumPy这个python工具包付出的成本应该是不大的. NumPy的基本的object是多维数组,是一个有同样类型的数字等构成的一张表格,能够通过元组进行索 ...
- HDOJ 4460 Friend Chains 图的最长路
类似于树的直径,从随意一个点出发,找到距离该点最远的且度数最少的点. 然后再做一次最短路 Friend Chains Time Limit: 2000/1000 MS (Java/Others) ...
- android 二次按返回键退出client
android中有的app退出client时弹出对话框的方法,有的是点击二次,第一次是提示用户是否退出client,第二次点击才是真正的退出app.这是用二次点击返回键的时间间隔推断, 今天就实现这简 ...
- session timer(一)
功能介绍 SIP并没有为所建立的会话定义存活机制. 虽然用户代理能够通过会话特定的机制推断会话是否超时,可是代理server却做不到这点. 如此一来.代理server有时会无法推断会话是否还是活动的. ...
- es62
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- js02---字符串
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...