上下文
我们有一个模型,其中每个元素
都有一个元素种类
和0到N个特征
。每个特征
仅属于一个元素
并具有一个特征名称
。
建模如下表:
ELEMENTS
elem_id int not null -- PK
elem_elki_id int not null -- FK to ELEMENT_KINDS
-- more columns with elements data
ELEMENT_KINDS
elki_id int not null -- PK
-- more columns with elements kinds data
FEATURES
feat_id int not null -- PK
feat_elem_id int not null -- FK to ELEMENTS
feat_fena_id int not null -- FK to FEATURE_NAMES
-- more columns with features data
FEATURE_NAMES
fena_id int not null -- PK
-- more columns with feature_names data
要求
有一项新要求,即用要素种类
表替换要素名称
表。
每个(元素种类,特征名称)
对都有一个(且仅有一个)特征种类
。
模型中的更改是添加新列并创建新表:
ALTER TABLE features ADD feat_feki_id int null;
CREATE TABLE FEATURE_KINDS
(
feki_id int not null, -- PK
feki_elki_id int not null, -- FK to ELEMENT_KINDS
feki_fena_id int null, -- FK* to FEATURE_NAMES
-- more columns with feature kinds data
)
*feki_fena_id
实际上是一个临时列,显示哪个功能名称
用于创建每种功能类型
。填充 feat_feki_id
后,feki_fena_id
应与 feat_fena_id
和功能名称
表一起丢弃。
问题
成功填充features kind
表后,我们尝试使用以下查询填充feat_feki_id
列:
MERGE INTO features F
USING
(
SELECT *
FROM elements
INNER JOIN feature_kinds
ON elem_elki_id = feki_elki_id
) EFK
ON
(
F.feat_elem_id = EFK.elem_id AND
F.feat_fena_id = EFK.feki_fena_id
)
WHEN MATCHED THEN
UPDATE SET F.feat_feki_id = EFK.feki_id;
这适用于带有测试数据的小案例场景,但在生产中我们有~2000万元素
和~2000feature_kinds
并且大约需要一个小时才会抛出ORA-30036:无法在撤消表空间'UNDOTBS1'中将段扩展8错误。
问题
有什么方法可以提高 MERGE
的性能,使其正常工作吗? (也许我缺少一些索引?)
还有其他替代方法来填写 feat_feki_id
列吗? (我们已经尝试使用 UPDATE
而不是 MERGE
获得类似的结果)
最佳答案
目前尚不清楚是否出现了问题,或者您的撤消段是否太小。您可以在不得到 ORA-30036 的情况下执行以下语句吗?
UPDATE features f SET f.feat_feki_id = 12345;
如果这不起作用,您只需增加撤消段的大小即可。 Kludges 可用于分块进行更新,但您实际上不必这样做。
假设这不是一个简单的 UNDO 大小问题,您可以做的一件事是确保您的 MERGE
(或 UPDATE
)按照行出现的顺序更新行你的 table 。否则,您可能会一遍又一遍地重新访问相同的 block ,这确实会损害性能并增加 UNDO 使用率。几年前,我在一次类似的操作中遇到了这个问题,当我最终弄清楚时,我感到很震惊。
为了避免我遇到的问题,你需要这样的东西:
MERGE INTO features F
USING
(
SELECT f.feat_id, fk.feki_id
FROM features f
INNER JOIN elements e ON e.elem_id = f.feat_elem_id
INNER JOIN feature_kinds fk ON fk.feki_elki_id = e.elem_elki_id and fk.feki_fena_id = f.feat_fena_id
-- Order by the ROWID of the table you are updating to ensure you are not revisiting the same block over and over
ORDER BY f.rowid
) EFK
ON
(
F.feat_id = efk.feat_id )
)
WHEN MATCHED THEN
UPDATE SET F.feat_feki_id = EFK.feki_id;
我可能弄错了您的数据模型,但关键点是在 MERGE
查询中包含 FEATURES
表和 ORDER BY features.rowid
确保更新按行顺序发生。
关于sql - 使用大表时提高 MERGE 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41350840/