这条sql如何优化或改写?

[复制链接]
查看11 | 回复8 | 2015-3-6 11:58:39 | 显示全部楼层 |阅读模式
本帖最后由 panda_rabbit 于 2014-1-22 15:37 编辑
SELECT COUNT(1)
FROM CU_CUSTOMER_EXT CCE
WHERE((SELECT COUNT(1)
FROM TK_PHONE TK

,TK_PHONE_LINEL

,TK_PHONE_PROCESS P
WHERETK.TASK_ID = L.TASK_LINE_TASK
ANDL.TASK_LINE_ID = P.TASK_PROC_TASK_LINE
ANDL.TASK_LINE_CUSTOMER = CCE.CUSTOMER_ID
ANDP.TASK_PROC_ISINTERACT = 1
ANDTRUNC(TASK_PROC_PLANED_DATE) >=

TO_DATE('2013-12-15'

,'YYYY-MM-DD')
ANDTRUNC(TASK_PROC_PLANED_DATE) TM截图1.png (17.36 KB, 下载次数: 7)
下载附件
2014-1-22 15:34 上传

由于有条件L.TASK_LINE_CUSTOMER = CCE.CUSTOMER_ID,并且CU_CUSTOMER_EXT 表数据量较大,导致嵌套的统计执行次数过多,怎么优化或改写呢?


回复

使用道具 举报

千问 | 2015-3-6 11:58:39 | 显示全部楼层
TASK_PROC_PLANED_DATE和TASK_PROC_PLANED_DATE 2个日期字段是哪个表的字段
回复

使用道具 举报

千问 | 2015-3-6 11:58:39 | 显示全部楼层
看不懂的是,明明 是P.TASK_PROC_ISINTERACT = 1,为什么在执行计划里面 有nvl ?
回复

使用道具 举报

千问 | 2015-3-6 11:58:39 | 显示全部楼层
这语句是等价的吗?
with t as{
SELECT CCE.CUSTOMER_ID
FROM CU_CUSTOMER_EXT CCE

,TK_PHONE TK

,TK_PHONE_LINEL

,TK_PHONE_PROCESS P
WHERETK.TASK_ID = L.TASK_LINE_TASK
ANDL.TASK_LINE_ID = P.TASK_PROC_TASK_LINE
ANDL.TASK_LINE_CUSTOMER = CCE.CUSTOMER_ID
ANDP.TASK_PROC_ISINTERACT = 1
ANDTRUNC(TASK_PROC_PLANED_DATE) >=

TO_DATE('2013-12-15'

,'YYYY-MM-DD')
ANDTRUNC(TASK_PROC_PLANED_DATE) =

TO_DATE('2013-12-15', 'YYYY-MM-DD')
AND TRUNC(TASK_PROC_PLANED_DATE) 复制代码
回复

使用道具 举报

千问 | 2015-3-6 11:58:39 | 显示全部楼层
没错,是我的话,也是和4楼差不多的写法
回复

使用道具 举报

千问 | 2015-3-6 11:58:39 | 显示全部楼层
illinux 发表于 2014-1-22 16:13
TASK_PROC_PLANED_DATE和TASK_PROC_PLANED_DATE 2个日期字段是哪个表的字段

是TK_PHONE_PROCESS的,而且TRUNC(TASK_PROC_PLANED_DATE)上有索引,但用索引提示后更慢。
回复

使用道具 举报

千问 | 2015-3-6 11:58:39 | 显示全部楼层
本帖最后由 panda_rabbit 于 2014-1-22 17:22 编辑
hh7yx 发表于 2014-1-22 17:09
还有你这种写法我总觉的很别扭啊。。。



是开发写的,测试人员测出这里慢,所以我拿出sql来分析下。我也觉得sql别扭,反正我是写不出逻辑这么复杂的sql来。
回复

使用道具 举报

千问 | 2015-3-6 11:58:39 | 显示全部楼层
hh7yx 发表于 2014-1-22 17:09
还有你这种写法我总觉的很别扭啊。。。

你那里面少了个GROUP BY
主要是复杂的嵌套查询导致走FILTER,子查询被执行了285K次。。。想效率高很难
改写就OK了,如果不OK就统计信息的问题了
回复

使用道具 举报

千问 | 2015-3-6 11:58:39 | 显示全部楼层
hgjncn123 发表于 2014-1-22 17:00
这语句是等价的吗?
with t as{

我试了下,改为你的写法后,查询结果跟原sql一致,感谢。
改写后的sql为:
WITH T AS
(SELECT CCE.CUSTOMER_ID
FROM CU_CUSTOMER_EXTCCE
,TK_PHONE TK
,TK_PHONE_LINEL
,TK_PHONE_PROCESS P
WHERETK.TASK_ID = L.TASK_LINE_TASK
ANDL.TASK_LINE_ID = P.TASK_PROC_TASK_LINE
ANDL.TASK_LINE_CUSTOMER = CCE.CUSTOMER_ID
ANDP.TASK_PROC_ISINTERACT = 1
ANDTRUNC(TASK_PROC_PLANED_DATE) >=
TO_DATE('2013-12-15'

,'YYYY-MM-DD')
ANDTRUNC(TASK_PROC_PLANED_DATE) <=
TO_DATE('2014-1-14'

,'YYYY-MM-DD')
GROUPBY CCE.CUSTOMER_ID
HAVING COUNT(CCE.CUSTOMER_ID) BETWEEN 1 AND 3)
SELECT COUNT(1) FROM T;
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行