2009-08-25 6 views
23

J'ai une requête commeoracle supprimer requête qui prend trop de temps

DELETE from tablename where colname = value; 

qui prend terriblement longtemps pour exécuter. Quelle pourrait être la raison? J'ai un index sur colname.

+0

Pourriez-vous poster le plan d'explication de votre requête (dans SQL * Plus, exécutez "SET AUTOTRACE ON EXPLAIN" puis votre requête)? –

+0

SQL> définir autotrace sur expliquer SQL> delete from nom_table où nid = 1250626; 1 ligne supprimée. Plan d'exécution ------------------------------------------------ ---------- 0 DELETE STATEMENT Optimizer = ALL_ROWS (Coût = 2 Card = 1 Bytes = 48) 1 0 SUPPRIMER 'tablename' 2 1 INDEX (UNIQUE SCAN) de 'PK_tablename' (INDEX (UNIQUE)) (Coût = 1 carte = 1 octet = 48) Ceci est pour la suppression de 1 ligne. La requête d'origine a une condition '> =', que je ne pouvais pas voir un achèvement jusqu'à environ 20 minutes. Même avec '=', cela prend plus d'une minute – Ajay

+0

Qu'en est-il des performances de * SELECT * FROM nom_table WHERE nid = 1250626; *? – Christian13467

Répondre

30

Il pourrait y avoir plusieurs explications pour expliquer pourquoi votre requête prend beaucoup de temps:

  1. Vous pourriez être bloqué par une autre session (le plus probable). Avant de supprimer, vous devez vous Noone que d'autre verrouille les lignes, par exemple: problème SELECT NULL FROM tablename WHERE colname=:value FOR UPDATE NOWAIT,
  2. Il pourrait y avoir un ON DELETE TRIGGER qui fonctionne plus,
  3. Vérifier UNINDEXED REFERENCE CONSTRAINTS pointant vers cette table (il y a une script from AskTom qui aidera vous déterminez si de telles clés étrangères non indexées existent).
+0

merci pour la réponse, mais pas les options 1 et 2. – Ajay

+2

3ème était en fait la solution :). Maintenant, il s'exécute dans les 2 secondes! – Ajay

+0

heureux d'aider =). En fait, je devrais probablement avoir mis le troisième point dans la place numéro 1, car il est le plus susceptible d'être négligé –

4

Il se peut que votre table soit liée à plusieurs tables ayant un nombre de lignes énorme.

+0

yup. correct! C'était une énorme table parent – Ajay

2

Quelle est la sélectivité de cet indice? Si votre table a un million de lignes et que cette valeur en touche cent cinquante mille, votre index est inutile. En fait, il peut être pire qu'inutile si elle est réellement utilisée. Rappelez-vous, un DELETE est comme une instruction SELECT: nous pouvons ajuster son chemin d'accès. De plus, les suppressions occupent beaucoup d'espace de table d'annulation, ce qui fait que vous risquez de souffrir de conflits si le système est très sollicité. Dans un système multi-utilisateur, une autre session peut avoir un verrou sur les lignes que vous souhaitez supprimer.

Avez-vous des déclencheurs ON DELETE? Avez-vous des contraintes de clé étrangère DELETE CASCADE? Étant donné tout ce que vous dites, et en particulier la colonne en question étant la clé primaire de sorte que vous essayez de supprimer une seule ligne, si cela prend beaucoup de temps, il est beaucoup plus probable que d'autres processus ou l'utilisateur a un verrou sur la ligne. Est-ce que quelque chose apparaît dans V$LOCK?

+0

Non Activé Supprimer les déclencheurs. La table a plus de 1 million de lignes. La colonne indexée est la clé primaire. Pas de contraintes SUPPRIMER CASCADE. J'ai encore une autre table parente avec> 1 million de lignes prenant juste une seconde pour supprimer une ligne! – Ajay

0

Votre table contient-elle plus d'enregistrements?
Existe-t-il des programmes récursifs (certaines boucles imbriquées, etc.) s'exécutant sur le serveur de base de données?
Vérifiez les problèmes réseau si le serveur de base de données se trouve sur des machines différentes?

+0

Pas de pgms récursif côté serveur. Pas de problème nm – Ajay

0

Je vais donc poster mon expérience. Ça pourrait être utile pour quelqu'un.

La requête

delete from foo 
where foo_id not in ( 
    select max(foo_id) from foo group by foo_bar_id, foo_qux_id 
); 

a pris 16 sec. la suppression de 1700 enregistrements de 2300 au total dans le tableau foo.

J'ai vérifié tous les index sur les clés étrangères comme indiqué dans d'autres réponses. Cela n'a pas aidé.

Solution:

Changé la requête

delete from foo 
where foo_id in ( 
    select foo_id from foo 
    minus 
    select max(foo_id) from foo group by foo_bar_id, foo_qux_id 
); 

J'ai changé not in-in et utilisé minus pour obtenir un résultat correct.

Maintenant, la requête s'exécute en 0,04 sec.

Questions connexes