一個邏輯讀過千萬的SQL找到解決辦法

[复制链接]
查看11 | 回复9 | 2010-10-8 09:28:52 | 显示全部楼层 |阅读模式
/* Formatted on 2011/03/09 17:52 (Formatter Plus v4.8.8) */
UPDATE /*+index(d)*/ecard_hrms_emp_total d
SET (d.empsex, d.empname, d.empbirthday, d.nationid, d.empidno,
d.empstatusid, d.emptypeid, d.empcardtid, d.grdid, d.empmemo, d.dptno,
d.dptname, d.totalno, d.totalname, d.createuser, d.createdate,
d.maintuser, d.maintdate, d.SIGN, d.remark, d.dptid,
d.card_group_date) =

(SELECT s.empsex, s.empname, s.empbirthday, s.nationid, s.empidno,

s.empstatusid, s.emptypeid, s.empcardtid, s.grdid,

s.empmemo, s.dptno, s.dptname, s.totalno, s.totalname,

s.createuser, s.createdate, s.maintuser, s.maintdate,

s.SIGN, s.remark, s.dptid, s.card_group_date

FROM ecard_hrms_emp_total_movin_tmp s

WHERE d.empno = s.empno)
WHERE d.empno IN (SELECT empno

FROM ecard_hrms_emp_total_movin_tmp);

ecard_hrms_emp_total_movin_tmp有將近3.5萬筆數據
ecard_hrms_emp_total有108萬
先用游標讀出ecard_hrms_emp_total_movin_tmp表的工號信息,再逐個工號update ecard_hrms_emp_total 表相關欄位
新SQL邏輯讀是原來的1/20,明天再找開發協商改存儲過程
回复

使用道具 举报

千问 | 2010-10-8 09:28:52 | 显示全部楼层
修改了什么地方?HINT?
前后执行计划和逻辑读都有什么变化?
回复

使用道具 举报

千问 | 2010-10-8 09:28:52 | 显示全部楼层
把1条复杂的update转换成数千条简单的update,是否可行?
回复

使用道具 举报

千问 | 2010-10-8 09:28:52 | 显示全部楼层
这本身是一个存储过程的SQL
现在用游标来分解,一条empno update一次,执行计划完全走索引,这样单条update语句逻辑读才12
12×3.5万笔empno才42万,原来是1000万出头,最好时也有将近850万的逻辑读
新SQL
v_empno ecard_hrms_emp_total_movin_tmp.empno%type;
....
cursor a_cursor is select empno from ecard_hrms_emp_total_movin_tmp;
open a_cursor;
Loop
Fetcha_cursorinto v_empno;
exit when a_cursor%notfound;
/* Formatted on 2011/03/09 17:52 (Formatter Plus v4.8.8) */
UPDATE ecard_hrms_emp_total d
SET (d.empsex, d.empname, d.empbirthday, d.nationid, d.empidno,
d.empstatusid, d.emptypeid, d.empcardtid, d.grdid, d.empmemo, d.dptno,
d.dptname, d.totalno, d.totalname, d.createuser, d.createdate,
d.maintuser, d.maintdate, d.SIGN, d.remark, d.dptid,
d.card_group_date) =

(SELECT s.empsex, s.empname, s.empbirthday, s.nationid, s.empidno,

s.empstatusid, s.emptypeid, s.empcardtid, s.grdid,

s.empmemo, s.dptno, s.dptname, s.totalno, s.totalname,

s.createuser, s.createdate, s.maintuser, s.maintdate,

s.SIGN, s.remark, s.dptid, s.card_group_date

FROM ecard_hrms_emp_total_movin_tmp s

WHEREs.empno=v_empno)
WHERE d.empno =v_empno;
end loop;
commit;
[ 本帖最后由 spider0283 于 2011-3-9 20:17 编辑 ]
回复

使用道具 举报

千问 | 2010-10-8 09:28:52 | 显示全部楼层
头晕,等cursor大的时候,你又要改了
回复

使用道具 举报

千问 | 2010-10-8 09:28:52 | 显示全部楼层
ecard_hrms_emp_total_movin_tmp 表记录数量少,empno上有索引
回复

使用道具 举报

千问 | 2010-10-8 09:28:52 | 显示全部楼层
看看有帮助么
http://www.dbforums.com/oracle/1 ... e-using-select.html
回复

使用道具 举报

千问 | 2010-10-8 09:28:52 | 显示全部楼层
試過了,用exists沒效果
今天早上上了線,效果相當好,幾秒鐘就update完3.7萬筆數據
回复

使用道具 举报

千问 | 2010-10-8 09:28:52 | 显示全部楼层
表数据才3.5W和108W就有那么多逻辑读,很明显是因为NEST LOOP,甚至filter。如果用HASH走,一定会非常快。
你把一条SQL改成cursor的显得过于复杂,如果是JOB到也无所谓。
回复

使用道具 举报

千问 | 2010-10-8 09:28:52 | 显示全部楼层
走hash join一樣效能很差
回复

使用道具 举报

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

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行