【发布时间】:2011-09-05 17:25:03
【问题描述】:
这已经困扰了我大约 4 个小时,所以我认为是时候寻求帮助了。我在网上找不到类似的东西,但主要是因为这些值非常具体,我不太确定要寻找什么......
这是我在使用 SQLPlus 10.2.0.5 中运行的 Oracle 脚本时遇到的问题。
问题:
(姓名和真实数据已更改以保护嫌疑人的身份) 我有一个名为 MONKEYS 的表和一个名为 MONKEY_PUZZLES 的表,它们看起来有点像这样:
猴子
- MONKEY_ID
- GIRAFFE_ID
- MONKEY_PUZZLE_ID
MONKEY_PUZZLES
- MONKEY_PUZZLE_ID
- GIRAFFE_ID
MONKEY_PUZZLES.GIRAFFE_ID 和 MONKEYS.GIRAFFE_ID 匹配,但每个 MONKEY_PUZZLE 有 n 个 MONKEY(因此 MONKEY_PUZZLES.GIRAFFE_ID 1 可能匹配 MONKEY.MONKEY_ID 1、2 和 334)。
我想根据 MONKEY_PUZZLES.MONKEY_PUZZLE_ID 字段设置 MONKEYS.MONKEY_PUZZLE_ID 字段,因为目前我的 MONKEYS.MONKEY_PUZZLE_ID 字段为空。我有以下索引:
- MONKEYS.MONKEY_ID(带索引的主键)
- MONKEYS.GIRAFFE_ID
- MONKEY_PUZZLES.MONKEY_PUZZLE_ID(带索引的主键)
- MONKEY_PUZZLES.GIRAFFE_ID
MONKEYS 表中有超过 160 万行,MONKEY_PUZZLES 表中有超过 50,000 行。
我最初使用的是以下查询:
UPDATE MONKEYS M SET M.MONKEY_PUZZLE_ID =
(SELECT MP.MONKEY_PUZZLE_ID FROM MONKEY_PUZZLES MP
WHERE M.GIRAFFE_ID = MP.GIRAFFE_ID
AND MP.GIRAFFE_ID IS NOT NULL);
但是,此脚本需要大约 2 分钟才能完成从 0% 到 92.67%,然后需要 25 多分钟才能完成 94%。我最终停止了脚本。我运行了几次(我正在使用不同的索引和 DBMS_STATS),但每次都会达到 92.67% 并崩溃。
所以我想这一定是我的剧本。我回到第一格,吃了一根香蕉,说了很多“Oook”,然后想出了以下变体脚本,它更明确:
UPDATE MONKEYS M2 SET M2.MONKEY_PUZZLE_ID =
(SELECT X.MPID FROM
(SELECT M.MONKEY_ID MID, MP.MONKEY_PUZZLE_ID MPID
FROM MONKEYS M INNER JOIN MONKEY_PUZZLES MP
ON MP.GIRAFFE_ID = M.GIRAFFE_ID) X
WHERE X.MID = M2.MONKEY_ID);
但是,这很垃圾。即使使用我的索引,也需要超过 5 分钟才能达到 2%,所以我放弃了那个。
然后我想出了以下变体,我对此非常满意:
UPDATE MONKEYS M SET M.MONKEY_PUZZLE_ID =
(SELECT MP.MONKEY_PUZZLE_ID
FROM MONKEY_PUZZLES MP
WHERE M.GIRAFFE_ID = MP.GIRAFFE_ID
AND EXISTS
(SELECT 1 FROM MONKEY_PUZZLES MP2
WHERE M.GIRAFFE_ID = MP2.GIRAFFE_ID));
然而,我真的不敢相信自己的眼睛,这个脚本的表现几乎和第一个一模一样;运行大约 2 分钟,从 0% 到 92.67% 完成,然后需要很长时间才能更进一步。 92.67%是什么?!
区块总数为 41,717,因此在似乎显着放缓之前达到了大约 38,000 个区块。
如果您想知道,我在单独的 SQLPlus 会话中使用以下查询来计算完成百分比:
SELECT X.*, TO_CHAR(SYSDATE, 'HH24:MI:SS') TIMESTAMP
FROM (select sid, serial#, opname, sofar, totalwork,
round(sofar/totalwork*100,2) "% Complete" from v$session_longops) X
WHERE "% Complete" < 100 and totalwork > 0;
(这是它的变体:http://searchoracle.techtarget.com/tip/Tracking-the-progress-of-long-running-queries)
请帮助一只可怜的老虎摆脱痛苦!
附:我打算让脚本在一夜之间运行,如果达到 100%,我会在早上更新。
编辑:它在 57 分钟后最终达到 100%(所以不是那么糟糕),但考虑到它在 2 分钟内达到 92.67%,这太可怕了!
【问题讨论】:
-
您应该做几件事:为您的表创建优化器统计信息并获取相应语句的执行计划。此外,您应该检查查询卡住时的等待事件。
-
执行计划在这里真的很有帮助。另外,您所有的 monkeys.monkey_puzzle_id 字段都是 NULL,还是添加
WHERE monkey_puzzle_id IS NULL可能有帮助? -
谢谢@eaolson。我所有的monkeys.monkey_puzzle_ids 都是空的。 @steve,我使用
DBMS_STATS.GENERATE_SCHEMA_STATS(OWNNAME=>'JUNGLE',OPTIONS=>'GATHER AUTO')来生成关于我设置的索引的统计信息。还有什么可以帮助的吗? -
你伪装的表名让我很兴奋。
标签: sql oracle sql-update sqlplus