2010-02-04 5 views
2

J'ai une table dans une base de données Oracle (10g XE), et je vais la nettoyer et ne conserver que les trois enregistrements récents de chaque compte. Voici ce que je fais en ce moment:Amélioration des performances de conservation des trois enregistrements récents de chaque requête de compte

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; 
/

Et puis je vais laisser tomber la vieille table, Renommez ce nouveau à ancien et ajouter des contraintes.

Mais le problème est que le code ci-dessus s'exécute pour toujours (~ 3-4 heures) pour environ 1 million d'enregistrements dont environ la moitié doit être supprimée.

Y at-il un moyen d'améliorer les performances de ce?

Répondre

3

Au lieu de créer une table vide et alimenter de façon RBAR créer une table avec les lignes que vous voulez ....

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 
/

Ensuite, passez directement à la partie renommée de votre plan.

Questions connexes