网站维护建设费应计入科目,高端营销型网站制作,做网站不给钱,汽车网站营销原文#xff1a;http://blog.csdn.net/liangweiwei130/article/details/37882503
------------------------------------------------- 在做项目的过程中#xff0c;一个页面使用类似如下的SQL查询数据#xff0c;为了保密和使用方便#xff0c;我把项目中有关的表名和字段…原文http://blog.csdn.net/liangweiwei130/article/details/37882503
------------------------------------------------- 在做项目的过程中一个页面使用类似如下的SQL查询数据为了保密和使用方便我把项目中有关的表名和字段替换使用ORACLE数据库中的系统表和字段。 在我所做的项目中类似ALL_TABLES的表中大概有8W多条数据下面这个查询SQL很慢。 [sql] view plain copy print? 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不存在了。 [sql] view plain copy print? 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 总结 在FILTER中NOT EXISTS后的SQL语句多次执行本来数据量就很大每次都要执行一遍结果可想而知。但是使用HINT MATERIALIZE和WITH AS 结合使用把内联视图实体化执行过程中会创建基于视图的临时表。这样就不会每次NOT EXISTS都去执行一遍大数据表的扫描只需要扫描一次即可。 但是是不是可以在WITHAS中的每个语句都实体化那如果WITH AS中的语句只被调用一次的话最好还是不要使用HINT MATERIALIZE因为使用HINT MATERIALIZE第一次查询会创建基于视图结果的临时表这也耗费一些时间。多次使用的话可以使用HINT MATERIALIZE。