J'utilise la requête mentionnée pour supprimer plus de 250 millions de lignes de ma table et cela prend plus de temps
J'ai essayé avec la limite t_delete avec jusqu'à 20000.
La suppression est encore lente.
/ p>
Veuillez suggérer quelques optimisations dans le même code pour faire mon travail plus rapidement.
DECLARE TYPE tt_delete IS TABLE OF ROWID; t_delete tt_delete; CURSOR cIMAV IS SELECT ROWID FROM moc_attribute_value where id in (select id from ORPHANS_MAV); total Number:=0; rcount Number:=0; Stmt1 varchar2(2000); Stmt2 varchar2(2000); BEGIN --- CREATE TABLE orphansInconsistenDelProgress (currentTable VARCHAR(100), deletedCount INT, totalToDelete INT); --- INSERT INTO orphansInconsistenDelProgress (currentTable, deletedCount,totalToDelete) values ('',0,0); Stmt1:='ALTER SESSION SET parallel_degree_policy = AUTO'; Stmt2:='ALTER SESSION FORCE PARALLEL DML'; EXECUTE IMMEDIATE Stmt1; EXECUTE IMMEDIATE Stmt2; --- ALTER SESSION SET parallel_degree_policy = AUTO; --- ALTER SESSION FORCE PARALLEL DML; COMMIT; --- MOC_ATTRIBUTE_VALUE SELECT count(*) INTO total FROM ORPHANS_MAV; UPDATE orphansInconsistenDelProgress SET currentTable='ORPHANS_MAV', totalToDelete=total; rcount := 0; OPEN cIMAV; LOOP FETCH cIMAV BULK COLLECT INTO t_delete LIMIT 2000; EXIT WHEN t_delete.COUNT = 0; FORALL i IN 1..t_delete.COUNT DELETE moc_attribute_value WHERE ROWID = t_delete (i); COMMIT; rcount := rcount + 2000; UPDATE orphansInconsistenDelProgress SET deletedCount=rcount; END LOOP; CLOSE cIMAV; COMMIT; END; /
3 Réponses :
peut-être utiliser SQL TRUNCATE TABLE,
Tronquer la table est plus rapide et utilise moins de ressources que la commande DELETE TABLE.
Il souhaite supprimer des enregistrements spécifiques et non la table entière.
Une seule requête parallèle Oracle peut simplifier le code et améliorer les performances.
declare execute immediate 'alter session enable parallel dml'; delete /*+ parallel */ from moc_attribute_value where id in (select id from ORPHANS_MAV); update OrphansInconsistenDelProgress set currentTable = 'ORPHANS_MAV', totalToDelete = sql%rowcount; commit; end; /
En général, nous souhaitons laisser Oracle diviser la tâche en morceaux ou utiliser notre propre segmentation personnalisée. Le code d'origine semble faire les deux: il lit les données par blocs, puis soumet chaque bloc pour qu'il soit divisé en une suppression parallèle. Cette approche génère beaucoup de petits morceaux et Oracle perd probablement beaucoup de temps sur des choses comme la coordination des threads.
La suppression d'un grand nombre de lignes coûte cher car il n'y a aucun moyen d'éviter REDO et UNDO. Vous voudrez peut-être examiner l'utilisation des options DDL, telles que la troncature d'une partition ou la suppression et la recréation de la table. (Mais attention à recréer des objets, il est difficile de recréer parfaitement des objets complexes. Nous avons tendance à oublier des choses comme les privilèges et les options de table.)
Le réglage du parallélisme et des gros travaux est compliqué. Il est important d'utiliser les meilleurs outils de surveillance, pour s'assurer qu'Oracle demande, alloue et utilise le bon nombre de processus parallèles et que le plan d'exécution est correct. L'un des grands avantages de l'utilisation d'une seule instruction SQL est que vous pouvez utiliser des rapports de surveillance SQL en temps réel pour surveiller la progression. Si vous disposez des licences Diagnostics and Tuning Pack, recherchez le SQL_ID
dans GV $ SQL
et générez le rapport avec sélectionnez dbms_sqltune.report_sql_monitor ("votre SQL_ID ici") ;
.
Si vous ne conservez qu'une fraction des lignes, il sera probablement beaucoup plus rapide de copier les lignes à conserver, puis d'échanger les tables et de supprimer l'ancienne table.
(Non, je ne connais pas le seuil à partir duquel cela est plus rapide que DELETEing.)