提高保留每个帐户查询的三个最近记录的性能

时间:2010-02-04 07:42:38

标签: performance oracle plsql

我在Oracle(10g XE)数据库中有一个表,我打算清理它,只保留每个帐户的三个最近记录。这就是我现在正在做的事情:

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个小时),大约有一百万条记录,其中大约有一半会被删除。

有没有办法改善这个性能?

2 个答案:

答案 0 :(得分:3)

不是创建一个空表并以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
/

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

答案 1 :(得分:0)

你可以用分析来做到这一点(虽然我自己并不熟悉它)。看看这个问题,这似乎解决了与你类似的情况:

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