ORACLE - 在大 table 上设置重复的 RANK,需要优化

ORACLE - Setting RANK of duplicated on a big table, optimization needed

这是更复杂算法的简化摘录。 问题是我有一个简单的 table C_HASH 像这样:

CREATE TABLE C_HASH
    (   
    HASH CHAR (48),
    RANK INTEGER
    );

首先,我用所有哈希值填充 table。但是因为我可以在HASH中有重复项,为了一一识别重复项我需要通过HASH设置RANK。

我做了这个 SQL 语句但是它太长了,我已经索引了 HASH 列,但没有效果:

UPDATE C_HASH a set RANK = ( select temp.rank from ( select rowid, rank() over ( PARTITION BY HASH ORDER BY ROWID ) rank from C_HASH ) temp where temp.rowid = a.rowid);

我要优化这个!有线索吗?

这将花费很长时间,因为您要更新所有行。但是您可以将逻辑简化为:

update c_hash h
    set rank = (select count(*)
                from c_hash h2
                where h2.hash = h.hash and h2.rowid <= h.rowid
               );

这应该是 table 以利用您现有的索引。

您可以使用 merge 语法:

merge into c_hash c
using (
    select rowid, row_number() over(partition by hash order by rowid) rank
    from c_hash
) c1
on (c1.rowid = c.rowid)
when matched then update set c.rank = c1.rank

Demo on DB Fiddle

示例数据:

HASH                                             | RANK
:----------------------------------------------- | ---:
foo                                              | null
foo                                              | null
foo                                              | null
bar                                              | null

结果:

HASH                                             | RANK
:----------------------------------------------- | ---:
foo                                              |    1
foo                                              |    2
foo                                              |    3
bar                                              |    1

如果您要更新很多行,使用 insert ... select 语法创建一个新的 table 可能更有效:

create table c_hash2 as
select hash, row_number() over(partition by hash order by rowid) as rank
from c_hash