我有一个包含大数据(大约1000万条记录)的表格,因此最简单的更新语句永远都可以使用。
例如:
update mesg
set archived = 1
, last_update = SYSDATE
where id = 0
and crea_date_time < '07/27/2011 13:53:36'
and archived = 0;
此声明大约需要3个小时。虽然我们在id上有索引,在crea_date_time上有复合索引,但没有触发器。
我是否可以采取任何改进措施来提高效果。
我尝试在存档上添加索引但没有效果。
这里有一些额外的信息。
CREATE TABLE "MESG"
(
"ID" NUMBER(3,0) NOT NULL ENABLE,
"UMIDL" NUMBER(10,0) NOT NULL ENABLE,
"UMIDH" NUMBER(10,0) NOT NULL ENABLE,
.
.
.
"ARCHIVED" NUMBER(1,0) NOT NULL ENABLE,
"LAST_UPDATE" DATE,
"CREA_DATE_TIME" DATE NOT NULL ENABLE,
.
.
.
CONSTRAINT "PK_RMESG" PRIMARY KEY ("AID", "UMIDH", "UMIDL") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE(INITIAL 524288 NEXT 524288 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT) TABLESPACE "XXXX_IDX" ENABLE
)
SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE
(
INITIAL 524288 NEXT 524288 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT
)
TABLESPACE "XXXX_MESG" ;
索引:
CREATE INDEX "E_RCREATIONDATE" ON "RMESG"
(
"CREA_DATE_TIME"
)
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE
(
INITIAL 524288 NEXT 524288 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT
)
TABLESPACE "XXXX_IDX" ;
CREATE UNIQUE INDEX "PK_RMESG" ON "RMESG"
(
"ID", "UMIDH", "UMIDL"
)
PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE
(
INITIAL 524288 NEXT 524288 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT
)
TABLESPACE "XXXX_IDX" ;
并且查询计划适用于具有180K记录的本地计算机
ID PID Operation Name Rows Bytes Cost CPU Cost IO Cost Temp space IN-OUT PQ Dist PStart PStop
0 UPDATE STATEMENT 1 44 877 6245703 877
1 0 UPDATE MESG
2 1 TABLE ACCESS BY INDEX ROWID MESG 1 44 877 6245703 877
3 2 INDEX RANGE SCAN IX_MESG_CREATIONDATE 158K 877 6245703 877
答案 0 :(得分:2)
我假设存档是伪 - boolean,可以是0或1.在这种情况下,优化器可能会选择忽略索引。
为了验证是否使用了索引,您可以尝试
explain plan for
update mesg set archived = :a,
last_update = :b
where id = :c and
crea_date_time < :d and
archived = :e;
然后
select * from table(dbms_xplan.display);
答案 1 :(得分:1)
如果您更新了很多行,索引将无法帮助您。它们只会改善对数据的访问。
对你而言,最重要的是UPDATE本身。
一个。用户是否读取/更新了此表?
如果没有,您可以尝试使用新数据重新创建表。
create table copy_table as
select case
when s.archived = 0 and s.crea_date_time < '07/27/2011 13:53:36' and s.id = 0
then 1 else s.archived as archived,
when s.archived = 0 and s.crea_date_time < '07/27/2011 13:53:36' and s.id = 0
then sysdate else s.last_update_date as last_update_date,
id,
other_columns
from mesg;
rename mesg to mesg_old;
rename copy_table to mesg;
B中。另一个想法/帮助是,如果你有许可证,可以在crea_date_time上对你的mesg表进行分区(我假设它是date
类型)。
在这种情况下,您的更新不会扫描整个表,但更重要的是,您可能永远不需要将其标记为存档内容。旧分区 - 旧数据。
℃。 CREA_DATE_TIME上的索引正在减慢您的更新。如果不是绝对必要,请放弃它。
答案 2 :(得分:1)
首先你真的想要跑:
update mesg
set archived = 1
, last_update = SYSDATE
where id = 0 and crea_date_time < '07/27/2011 13:53:36'
and archived <>1
(对于ORacle来说是正确的代码吗?或者确实是使用!=?或者可能存档的位置为null或者存档= 0,以及如何存储数据)
现在,您正在更改已归档的所有记录的last_update日期和已归档字段。因此,您可以更新已存档的数百万条记录。因此,不是更新自上次执行以来需要存档的120,000条记录,而是更新35,000,000条记录,其中大多数已经存档。可以在性能方面做出很大改变,只更新需要更新的记录。
接下来我不了解Oracle,但有时在SQl Server中批量运行大型更新/插入/删除会更快。那你有没有试过循环1000(或50000你可能需要测试,看看什么有效)?这可以减少桌面上的大量争用并使事情更快地运行。
答案 3 :(得分:1)
索引不是问题。这是更新。
我认为你必须深入等待分析,字典表v $ session_waits。如果您具有企业管理器数据库控制,则可以使用性能工具查看导致延迟的原因。我的猜测是,它与重做日志的IO性能有关,或者其他人提到锁定问题。
首先:
select
seq#, event, p1, p2, p3
from
v$session_wait_history
where
sid = <yoursid>
order by seq#
;
谷歌在oracle等待分析中,你会发现很多材料。
答案 4 :(得分:0)
即使是数据量,三个小时太长了。
您可以尝试修改查询以避免类型转换,将to_data函数应用于您的日期字符串(将此'07 / 27/2011 13:53:36'转换为日期)
但问题应该是锁,您可以使用Killing an oracle session to remove a lock脚本检查锁定。
此外,您可以在小更新中拆分大查询,有些人认为:
for each year:
begin transaction
update statement where year(date) = @year and other conditions
end transaction
答案 5 :(得分:0)
您应该进行表分区和索引分区。 性能会提高