Sql查询速度优化

lgoodbook 2015-12-22 03:39:45
 SELECT
(CASE
WHEN
(SELECT COUNT(*)
FROM EMPLOYEE
WHERE PERCOD = DB.PERID) > 1 THEN
(SELECT PERNAME
FROM EMPLOYEE
WHERE PERCOD = DB.PERID
AND ISDELETED = 0)
ELSE
(SELECT PERNAME
FROM EMPLOYEE
WHERE PERCOD = DB.PERID)
END) AS PERNAME
FROM BALANCE DB
LEFT JOIN BALANCE_BONUS DBB
ON DBB.ID = DB.BONUSID
WHERE DB.ISDELETED != 1
ORDER BY DB.ID;


多表查询。

(CASE
WHEN
(SELECT COUNT(*)
FROM EMPLOYEE
WHERE PERCOD = DB.PERID) > 1 THEN
(SELECT PERNAME
FROM EMPLOYEE
WHERE PERCOD = DB.PERID
AND ISDELETED = 0)
ELSE
(SELECT PERNAME
FROM EMPLOYEE
WHERE PERCOD = DB.PERID)
END) AS PERNAME
这一段代码会非常消耗查询时间。
作用是 排除 EMPLOYEE 表中PERCOD重复的数据 , ISDELETED字段为已删除。
首先查询级联的人员是否有重复数据,如果只有一条则显示这唯一的一条;
如果有多条,则显示ISDELETED字段为0的一条数据。

有没有大牛给个优化解决方法!!!
...全文
304 12 打赏 收藏 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
lgoodbook 2015-12-23
  • 打赏
  • 举报
回复
引用 7 楼 wildwave 的回复:
执行计划是指SQL语句的explain plan
查看方法有几种,可以搜一下



小灰狼W 2015-12-23
  • 打赏
  • 举报
回复
执行计划是指SQL语句的explain plan 查看方法有几种,可以搜一下
lgoodbook 2015-12-23
  • 打赏
  • 举报
回复
引用 5 楼 wildwave 的回复:
提供下执行计划
主表中有人员ID, 需要级联查询出来人员名称。 人员表中 人员离职 状态ISDELETED为1; 人员从一个子公司调入另一子公司,在人员表中会有2条数据,ID不变, ISDELETED标示离职(1)/调离(1) /在职(0). 我的SQL在最开始没有考虑这种情况,出现 单行子查询返回多个行 ,才在后面加入原帖代码!
小灰狼W 2015-12-23
  • 打赏
  • 举报
回复
提供下执行计划
lgoodbook 2015-12-23
  • 打赏
  • 举报
回复
引用 2 楼 wildwave 的回复:
SELECT    (SELECT MAX(pername)KEEP(dense_rank FIRST ORDER BY CASE ISDELETED WHEN 0 THEN 1 ELSE 2 END) FROM EMPLOYEE WHERE PERCOD = DB.PERID) AS PERNAME   FROM BALANCE DB   LEFT JOIN BALANCE_BONUS DBB   ON DBB.ID = DB.BONUSID  WHERE  DB.ISDELETED != 1  ORDER BY DB.ID;  EMPLOYEE 表上要有PERCOD 字段的索引。这个是关键
加了索引,查询时间在7S左右。
lgoodbook 2015-12-23
  • 打赏
  • 举报
回复
引用 1 楼 jdsnhan 的回复:
这么写,每行都要执行case里面的查询,效率肯定低啊。 换个思路, select percod from ( select PERCOD ,ifdeleted,row_number() over(partition by PERCOD order by ifdeleted ) rnum from EMPLOYEE ) where rnum = 1 先看看这句的执行效果就应该明白后续怎么写了

(select pername from
            (SELECT pername, percod, isdeleted,
             row_number() over(partition by percod order by isdeleted)as rr
              FROM employee  where 
                ) where rr =1 and percod = db.emplyeeid) 
                AS EMPLYEENAME
这种优化方法可以节省查询的一半时间,但是时间还是有点长的
小灰狼W 2015-12-23
  • 打赏
  • 举报
回复
SELECT    (SELECT MAX(pername)KEEP(dense_rank FIRST ORDER BY CASE ISDELETED WHEN 0 THEN 1 ELSE 2 END) FROM EMPLOYEE WHERE PERCOD = DB.PERID) AS PERNAME   FROM BALANCE DB   LEFT JOIN BALANCE_BONUS DBB   ON DBB.ID = DB.BONUSID  WHERE  DB.ISDELETED != 1  ORDER BY DB.ID;  EMPLOYEE 表上要有PERCOD 字段的索引。这个是关键
jdsnhan 2015-12-23
  • 打赏
  • 举报
回复
这么写,每行都要执行case里面的查询,效率肯定低啊。 换个思路, select percod from ( select PERCOD ,ifdeleted,row_number() over(partition by PERCOD order by ifdeleted ) rnum from EMPLOYEE ) where rnum = 1 先看看这句的执行效果就应该明白后续怎么写了
小灰狼W 2015-12-23
  • 打赏
  • 举报
回复
竟然几张表都是通过数据库连接过来的 避开dblink在该数据库(dblk_gap.....)本地执行这条语句试试 可以在该数据库中创建一张视图 create view xxxx as .......查询; 然后通过dblink调用视图 select ... from xxx@dblk_gap....
lgoodbook 2015-12-23
  • 打赏
  • 举报
回复

这是3楼的执行计划


这是2楼的执行计划
小灰狼W 2015-12-23
  • 打赏
  • 举报
回复
…… 给这个没有意义 要嫌慢的那条SQL语句的执行计划
lhdz_bj 2015-12-23
  • 打赏
  • 举报
回复
优化需要根据具体的SQL语句,执行计划和具体的数据环境进行。 楼主的这条SQL语句,可能涉及标量子查询,这种语句在11g前,如果主查询数据量较大,性能可能会比较差。

3,499

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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