代码之家  ›  专栏  ›  技术社区  ›  racetrack

提高每个账户查询三条最近记录的保存性能

  •  2
  • racetrack  · 技术社区  · 16 年前

    我在Oracle(10gXE)数据库中有一个表,我将清理它,并且只保留每个帐户的三个最近记录。我现在正在做的是:

    CREATE TABLE ACCOUNT_TRANSACTION_TMP NOLOGGING AS SELECT * FROM ACCOUNT_TRANSACTION WHERE 1=2;
    
    
    DECLARE
        CURSOR mbsacc_cur (account_id_var account_transaction.account_id%TYPE) IS
            SELECT * FROM account_transaction WHERE account_id = account_id_var ORDER BY transaction_time DESC;
    
        account_transaction_rec account_transaction%ROWTYPE;
    BEGIN
        FOR i IN (SELECT DISTINCT(account_id) FROM account_transaction) LOOP
            OPEN mbsacc_cur(i.account_id);
            LOOP
                FETCH mbsacc_cur INTO account_transaction_rec;
                EXIT WHEN mbsacc_cur%NOTFOUND OR mbsacc_cur%ROWCOUNT > 3;
                INSERT /*+ append */ INTO account_transaction_tmp VALUES account_transaction_rec;
            END LOOP;
            CLOSE mbsacc_cur;
        END LOOP;
    END;
    /
    

    然后我将删除旧表,将新表重命名为旧表,并添加约束。

    但问题是,上述代码将永远运行(约3-4小时),保持大约100万条记录,其中大约一半应该被删除。

    有什么方法可以提高这方面的性能吗?

    2 回复  |  直到 16 年前
        1
  •  3
  •   APC    16 年前

    不是创建一个空表并以RBAR方式填充,而是创建一个具有所需行的表…

    CREATE TABLE ACCOUNT_TRANSACTION_TMP NOLOGGING AS 
    SELECT account_id, col1, col2, col3, transaction_time from
        ( select at.*
                 , row_number()
                      over (partition by at.account_id 
                             order by at.transaction_time desc) as to_keep
     FROM ACCOUNT_TRANSACTION at)
    where to_keep <= 3
    /
    

    然后直接跳到计划的重命名部分。

        2
  •  0
  •   davek    16 年前

    你可以通过分析来做到这一点(尽管我自己对它一点也不精通)。看看这个问题,它似乎解决了类似于您的情况:

    http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1212501913138