Oracle 的 NOT EXISTS 很慢的问题

Phoenix546 2014-12-17 02:18:02
Oracle 数据库中建立一张临时表插入了13万记录,
然后做了一个简单的NOT EXISTS查询,发现非常的慢,
要消耗17分钟:
SELECT COUNT(*) FROM Temp_YY_INVENTORY ic
WHERE NOT EXISTS (
SELECT 1 FROM Temp_YY_INVENTORY ic1
WHERE ic1."cInvCode" = ic."cInvCode"
AND ( ic1.dEnd > ic.dEnd OR ic1."cAcc_Id" > ic."cAcc_Id" )
);
同样的代码,同样的表,我在SQL SERVER 2012上面跑,
只要不到2秒钟。

网上查询了一下,没有发现这方面的优化资料,
请问各位前辈,这里面有什么优化技巧吗?谢谢
...全文
924 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
Phoenix546 2014-12-17
  • 打赏
  • 举报
回复
另外请问版主,有什么Oracle方面的Sql优化类的书籍推荐的吗?谢谢
Phoenix546 2014-12-17
  • 打赏
  • 举报
回复
根据版主的方法,我测试了一下:
SELECT * FROM (
select T.*,ROW_NUMBER()OVER(PARTITION BY "cInvCode" ORDER BY "cAcc_Id" DESC, dEnd DESC) RN from Temp_YY_INVENTORY T )WHERE RN=1;

SELECT * FROM Temp_YY_INVENTORY T
WHERE ("cInvCode","cAcc_Id",dEnd) IN (SELECT "cInvCode",MAX("cAcc_Id"),MAX(dEnd) FROM Temp_YY_INVENTORY T GROUP BY "cInvCode");

SELECT "cInvCode",MAX("cAcc_Id"),MAX(dEnd),
MAX("cInvName")KEEP(DENSE_RANK LAST ORDER BY "cAcc_Id" DESC, dEnd DESC),
MAX(COST)KEEP(DENSE_RANK LAST ORDER BY "cAcc_Id" DESC, dEnd DESC)
FROM Temp_YY_INVENTORY T GROUP BY "cInvCode"
第一句和第三句会在13W条数据中提取每个cInvCode排序排第一的记录,取到了13624条, 第二句话的逻辑和我之前的NOT EXISTS一样,从13W条记录中取到了12679条, 第二句话没有取到的那945条属于不存在cAcc_Id和dEnd都处于最大的记录。 版主的回复完美的解决了我的问题,非常感谢
bw555 2014-12-17
  • 打赏
  • 举报
回复
SELECT * FROM (
select T.*,ROW_NUMBER()OVER(PARTITION BY "cInvCode" ORDER BY "dEnd" DESC,"cAcc_Id" DESC) RN from Temp_YY_INVENTORY T
)WHERE RN=1
类似需求使用分析函数处理 典型的去重处理需求 给你介绍几种去重的方式,你可以仿照实现下,最后一种效率应该是最高的,但是写起来比较麻烦 下面的语句实现的都是同一个id下取日期最大的记录
select ID,日期,其他字段
from (
    select ID,日期,其他字段,row_number() over(partition by ID order by 日期 DESC) rn
    from T
)where rn=1

select * from T T1
WHERE NOT EXISTS(SELECT 1 FROM T WHERE ID=T1.ID AND 日期>T1.日期)
 
select * from T
WHERE (ID,日期) IN (SELECT ID,MAX(日期) FROM T GROUP BY ID)
 
SELECT ID,MAX(日期),
MAX(字段1)KEEP(DENSE_RANK LAST ORDER BY 日期)
MAX(字段2)KEEP(DENSE_RANK LAST ORDER BY 日期)
……--其他字段同上
FROM T GROUP BY ID
Phoenix546 2014-12-17
  • 打赏
  • 举报
回复
感谢版主回复,这张表里面的数据内容是这样的: "id" ,"cAcc_Id" ,"iYear" ,"iPeriod" ,”dEnd“,"cInvCode" ,"cInvName" ,"fcost" id,账套号,年份,月份,日期,物资编码,物资名称,成本 我要取这一年所有物料在最大账套号中的最新成本, 代码中用COUNT(*)只是测试用的,最后还是要指定字段名的。
bw555 2014-12-17
  • 打赏
  • 举报
回复
SELECT COUNT(*) FROM (select distinct "cInvCode",dEnd,."cAcc_Id" from Temp_YY_INVENTORY)
只是count,也用不到exists啊

17,086

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧