当前位置: 代码迷 >> Oracle开发 >> 关于group 语句的优化,该怎么处理
  详细解决方案

关于group 语句的优化,该怎么处理

热度:47   发布时间:2016-04-24 06:41:11.0
关于group 语句的优化
这个表更新很慢数据量在10万条左右,但是需要5、6分钟,请高手帮忙提优化建议

UPDATE  RWD_TERMINAL_0851 A SET A.STR27 =(
SELECT  COUNT(1) FROM RWD_TERMINAL_0851 B 
WHERE B.str3='310000218201' AND B.str28='201402' AND B.STR21 = A.STR21
GROUP BY B.str28,B.str21)
WHERE A.STR28 ='201402'

------解决方案--------------------
MERGE RWD_TERMINAL_0851 A --
USING (
       SELECT B.str28, B.str21, COUNT(1) c
       FROM     RWD_TERMINAL_0851 B
       WHERE  B.str3 = '310000218201'
       AND    B.str28 = '201402'
       AND    B.STR21 = A.STR21
       GROUP  BY B.str28, B.str21) b --
ON (B.STR21 = A.STR21 AND B.str28 = A.STR28) --
WHEN MATCHED THEN UPDATE
SET    a.str27 = c

------解决方案--------------------
  我的理解,这种写法本质上是一条条的进行更新的。如果表a的STR21有10万个,就需要对表b做10万次的聚合操作。
我的思路就是,建张临时表保存表b所有的聚合结果,然后依据临时表更新目标表。这样,就会对表b仅仅聚合了一次,而不是10万次。  
 如有不妥,敬请指正。
1 在表a的列STR28上建立索引,确保A.STR28 ='201402'能走索引
2 建立一张事务级的临时表temp(),用于保存以下的结果集
SELECT B.STR21, COUNT(1) cnt FROM RWD_TERMINAL_0851 B 
WHERE B.str3='310000218201' AND B.str28='201402' 
GROUP BY B.str21

3 依据临时表的数据来更新目标表
 UPDATE  RWD_TERMINAL_0851 A SET A.STR27 =(
SELECT  B.cnt FROM temp B 
WHERE B.STR21 = A.STR21)
WHERE A.STR28 ='201402';
COMMIT

------解决方案--------------------
引用:
这个表更新很慢数据量在10万条左右,但是需要5、6分钟,请高手帮忙提优化建议

UPDATE  RWD_TERMINAL_0851 A SET A.STR27 =(
SELECT  COUNT(1) FROM RWD_TERMINAL_0851 B 
WHERE B.str3='310000218201' AND B.str28='201402' AND B.STR21 = A.STR21
GROUP BY B.str28,B.str21)
WHERE A.STR28 ='201402'


把 GROUP BY B.str28,B.str21 这个去掉,没什么正经用。另: B 表上可以根据这 3 列建一个IX。
------解决方案--------------------
with temp as(
SELECT  /* +materialize */COUNT(1)  cnt FROM RWD_TERMINAL_0851 B 
WHERE B.str3='310000218201' AND B.str28='201402' 
GROUP BY B.str28,B.str21
),
UPDATE  RWD_TERMINAL_0851 A SET A.STR27 =(select  cnt from temp c where a.STR21=c.STR21
)
WHERE A.STR28 ='201402'
大概是这样写的吧,自己看看调试下
  相关解决方案