select t.wp_status, t.is_send, count(1) "assignCount"
from (select t1.wp_status, t1.is_send
from t_crm_wp t1
where EXISTS (SELECT area_id
FROM t_area a
WHERE area_id = t1.area_id
START WITH a.area_id = 'GZ0000000000'
CONNECT BY PRIOR a.area_id = a.parent_area_id)
AND NOT EXISTS
(select 1
from t_crm_wp t
where t.wp_id = t1.wp_id
and (EXISTS
(select 1
from bst_sys_sysuser a
where (a.userid = t.user_id or
a.userid = t.check_id)
and EXISTS
(select 1
from t_area c
where a.area_id = c.area_id
and c.area_id <> 'GZ0000000000'
start with c.area_id = 'GZ0000000000'
connect by prior c.parent_area_id = c.area_id)))
and t.is_send = '1')) t
group by rollup(t.wp_status, t.is_send)
这个sql在本地执行需要1.6秒,在生产环境上是6分钟,怎么优化啊,我用的是ibatis,用##带变量,所以算是绑定变量方式传入的。本地数据10万左右吧,生产库上的有几百万吧!
from (select t1.wp_status, t1.is_send
from t_crm_wp t1
where EXISTS (SELECT area_id
FROM t_area a
WHERE area_id = t1.area_id
START WITH a.area_id = 'GZ0000000000'
CONNECT BY PRIOR a.area_id = a.parent_area_id)
AND NOT EXISTS
(select 1
from t_crm_wp t
where t.wp_id = t1.wp_id
and (EXISTS
(select 1
from bst_sys_sysuser a
where (a.userid = t.user_id or
a.userid = t.check_id)
and EXISTS
(select 1
from t_area c
where a.area_id = c.area_id
and c.area_id <> 'GZ0000000000'
start with c.area_id = 'GZ0000000000'
connect by prior c.parent_area_id = c.area_id)))
and t.is_send = '1')) t
group by rollup(t.wp_status, t.is_send)
这个sql在本地执行需要1.6秒,在生产环境上是6分钟,怎么优化啊,我用的是ibatis,用##带变量,所以算是绑定变量方式传入的。本地数据10万左右吧,生产库上的有几百万吧!
2. 把你的生产环境的执行计划贴出来,这样是看不出什么来的
3. 不要管别他说什么 not exists效率低之类的说法 :-)当然,你的语句里多少可以看出一点问题来:
你用了 start with...connect by,这个语句用在单表会运行的非常好,但是,你用在两表关联中就会有问题,所以,第一,你要做的就是,把start with...connect by 从内层关联中拉出来:strart with ... connect by ...
(内层关联)
这样,你的问题基本上就解决了
select t1.wp_status, t1.is_send
from t_crm_wp t1
where EXISTS (SELECT area_id
FROM t_area a
WHERE area_id = t1.area_id
START WITH a.area_id = 'GZ0000000000'
CONNECT BY PRIOR a.area_id = a.parent_area_id------
select t1.wp_status, t1.is_send
from t_crm_wp t1,
(SELECT area_id
FROM t_area a
START WITH a.area_id = 'GZ0000000000'
CONNECT BY PRIOR a.area_id = a.parent_area_id) t2
where t1.area_id = t2.area_id下面的connect by语句也这么改然后,在t_area表上加上字段 area_id的索引,我看,你用bitmap索引会非常好,你的area_id的distinct值会比较小,我想做完索引,运行
dbms_stats.gather_table_stat(user,'T_AREA', method_opt=>'for all indexed columns', cascade=>true);
你的主表是t_crm_wp,你说在本地数据有10多万,生产环境有几百万吧!但是你的no exists嵌套 查询:
not exists(select 1
from t_crm_wp t
where t.wp_id = t1.wp_id这样一搞,不就是几百万*几百万的开销吗?这样很消耗资源的,建议把no exists里面对t_crm_wp的条件语句移到外面来,就是不要t_crm_wp*t_crm_wp 的遍历,否则就麻烦了!当然以上几位说的connect by 用着where之后的条件判断也是比较消耗资源的啊!
哦,那我应该怎么改呢,这个sql不是我写的啊!写的那个人已经离职了!
select t.wp_status, t.is_send, count(1) "assignCount"
from (select t1.wp_status, t1.is_send
from t_crm_wp t1
where EXISTS (SELECT area_id
FROM t_area a
WHERE area_id = t1.area_id
START WITH a.area_id = 'GZ0000000000'
CONNECT BY PRIOR a.area_id = a.parent_area_id)
AND
(NOT EXISTS
(select 1
from bst_sys_sysuser a
where (a.userid = t1.user_id or
a.userid = t1.check_id)
and EXISTS
(select 1
from t_area c
where a.area_id = c.area_id
and c.area_id <> 'GZ0000000000'
start with c.area_id = 'GZ0000000000'
connect by prior c.parent_area_id = c.area_id))
or t1.is_send = '1'
)
/*(select 1
from t_crm_wp t
where t.wp_id = t1.wp_id
and (EXISTS
(select 1
from bst_sys_sysuser a
where (a.userid = t.user_id or
a.userid = t.check_id)
and EXISTS
(select 1
from t_area c
where a.area_id = c.area_id
and c.area_id <> 'GZ0000000000'
start with c.area_id = 'GZ0000000000'
connect by prior c.parent_area_id = c.area_id)))
and t.is_send = '1')*/
) t
group by rollup(t.wp_status, t.is_send)
我的area_id索引原来已经存在了!我执行你的sql语句报如下错误啊:SQL> dbms_stats.gather_table_stat(user,'T_AREA', method_opt=>'for all indexed columns', cascade=>true);dbms_stats.gather_table_stat(user,'T_AREA', method_opt=>'for all indexed columns', cascade=>true)ORA-00900: invalid SQL statement怎么搞?
from (select t1.wp_status, t1.is_send
from t_crm_wp t1
where EXISTS (SELECT area_id
FROM t_area a
WHERE area_id = t1.area_id
START WITH a.area_id = 'GZ0000000000'
CONNECT BY PRIOR a.area_id = a.parent_area_id)
AND
(NOT EXISTS
(select 1
from bst_sys_sysuser a
where (a.userid = t1.user_id or
a.userid = t1.check_id)
and EXISTS
(select 1
from t_area c
where a.area_id = c.area_id
and c.area_id <> 'GZ0000000000'
start with c.area_id = 'GZ0000000000'
connect by prior c.parent_area_id = c.area_id))
or t1.is_send = '1'
)
/*(select 1
from t_crm_wp t
where t.wp_id = t1.wp_id
and (EXISTS
(select 1
from bst_sys_sysuser a
where (a.userid = t.user_id or
a.userid = t.check_id)
and EXISTS
(select 1
from t_area c
where a.area_id = c.area_id
and c.area_id <> 'GZ0000000000'
start with c.area_id = 'GZ0000000000'
connect by prior c.parent_area_id = c.area_id)))
and t.is_send = '1')*/
) t
group by rollup(t.wp_status, t.is_send)
7樓的或者樓主能解釋下:爲什麽刪掉紅色的這句呢?
下面这段条件写错了吧:
AND
(NOT EXISTS
(select 1
from bst_sys_sysuser a
where (a.userid = t1.user_id or
a.userid = t1.check_id)
and EXISTS
(select 1
from t_area c
where a.area_id = c.area_id
and c.area_id <> 'GZ0000000000'
start with c.area_id = 'GZ0000000000'
connect by prior c.parent_area_id = c.area_id))
or t1.is_send = '1'
)楼主原语句的本意是:(统计)查出t_crm_wp中area_id='GZ0000000000'及其下属组织的数据,并排除在t_crm_wp中is_send='1'的check_id或user_id对应bst_sys_sysuser中User_id的组织为area_id='GZ0000000000'上属组织的数据。
楼主测试下,你原来的SQL结果和,oraclelogan 的优化SQL,以及下面的SQL结果是否一致:)
SELECT t1.wp_status, t1.is_send
FROM t_crm_wp t1
WHERE EXISTS (SELECT area_id
FROM t_area a
WHERE area_id = t1.area_id
START WITH a.area_id = 'GZ0000000000'
CONNECT BY PRIOR a.area_id = a.parent_area_id)
AND NOT EXISTS (SELECT 1
FROM bst_sys_sysuser a
WHERE (a.userid = t.user_id OR a.userid = t.check_id)
AND EXISTS (SELECT 1
FROM t_area c
WHERE a.area_id = c.area_id
AND c.area_id <> 'GZ0000000000'
START WITH c.area_id = 'GZ0000000000'
CONNECT BY PRIOR c.parent_area_id = c.area_id)
AND t.is_send = '1')