UPDATE [TABLE] SET [FIELD]=0 WHERE [FIELD] IS NULL [TABLE] is an Oracle database table with more than 700 million rows. I cancelled the SQL execution after it had been running for 6 hours.Is there any SQL hint that could improve performance? Or any other solution to speed that up?EDIT: This query will be run once and then never again.
5 Réponses :
Vous pouvez obtenir le même résultat sans mettre à jour en utilisant une table d'alimentation pour définir la valeur "Par défaut" sur 0. P>
Cela serait-il plus rapide cependant?
Ce serait plus rapide car il ne met pas à jour les données de la table en aucun cas, la définition de la table
OK, mais dans ce cas, je dois mettre à jour les lignes existantes et non seulement la définition de la table.
Non, vous racontez Oracle de transmettre la valeur par défaut zéro au lieu d'une valeur null chaque fois qu'elle rencontre une null - tout cela a lieu sur le traitement SELECT, il n'y a pas de mise à jour sur la table réelle.
-1 Désolé, cela ne fonctionne pas. Changer la valeur par défaut ne met pas à jour les lignes existantes. (Cette astuce "Mise à jour bon marché" ne fonctionne que si vous ajoutez une nouvelle colonne à la fois une contrainte par défaut et une contrainte NON NULL dans une seule opération - dans Oracle 11G.)
Tout d'abord, c'est une requête unique ou s'agit-il d'une requête récurrente? Si vous devez seulement le faire une fois que vous voudrez peut-être examiner la requête en mode parallèle. Vous devrez scanner toutes les lignes de toute façon, vous pourriez diviser la charge de travail vous-même avec des gammes de railid (parallélisme de soi-même de soi-même) ou utilisez des fonctionnalités intégrées Oracle.
supposant que vous souhaitez l'exécuter fréquemment et que vous souhaitez optimiser Cette requête, le nombre de lignes avec la colonne code> code> lorsque NULL sera éventuellement petite par rapport au nombre total de lignes. Dans ce cas, un index pourrait accélérer les choses. Oracle ne indice pas les lignes qui ont toutes les colonnes indexées telles que NULL, donc un indice sur le champ code> code> n'utilisera pas par votre requête (puisque vous voulez trouver toutes les lignes où soit: p> créer un index basé sur la fonction sur Comme il s'agit d'un scénario unique, vous pouvez utiliser le champ code> est null). p>
(champ, 0) code>, le
0 code> agira comme une pseudocolune non nulle et toutes les lignes seront indexées sur la table. Li >
(cas lorsque le champ est null, alors 1 extrémité) code>, cela n'indiquera que les lignes qui sont des nuls (l'index serait donc très compact). Dans ce cas, vous devriez réécrire votre requête: P>
Mettre à jour [Table] Définir [champ] = 0 où (le cas où le champ est null, 1 extrémité) = 1 code> p> p> p> p> p> p> L>
ul>
EDIT: h3>
parallèle code> indice: p>
Bonjour Vincent, il s'agit d'une requête unique. Mais merci de couvrant les deux scénarios (une requête unique / requête récurrente) dans votre réponse.
Nice utilisation de l'exemple de plan d'explication
Vincent a déjà répondu parfaitement à votre question, mais je suis curieux de "pourquoi" derrière cette action. Pourquoi mettez-vous la mise à jour de tous les NULL à 0? P>
Cordialement, Rob. P>
Bonne question, rob. C'est parce que les nulls ne sont pas suivis dans des index normaux.
Dans ce cas, faire une mise à jour et changer la sémantique de vos données semble assez drastique. Vous pouvez créer un index basé sur la fonction ou un sur ([champ] régulier, 1).
Oui, c'est une approche que nous envisageons. Merci
Quelques suggestions: p>
dépose des index contenant du champ avant d'exécuter votre relevé de mise à jour, puis de les ajouter plus tard. p> li>
Écrivez une procédure PL / SQL pour le faire qui commet chaque 1000 ou 10000 rangées. P> li> ol>
J'espère que cela aide. P>
sont d'autres utilisateurs mettent à jour les mêmes lignes de la table en même temps?
Si tel est le cas, vous pouvez frapper beaucoup de problèmes de concurrence (attendant des serrures) et cela vaut la peine de la rompre en transactions plus petites.
DECLARE v_cnt number := 1; BEGIN WHILE v_cnt > 0 LOOP UPDATE [TABLE] SET [FIELD]=0 WHERE [FIELD] IS NULL AND ROWNUM < 50000; v_cnt := SQL%ROWCOUNT; COMMIT; END LOOP; END; /
Assurez-vous que vous n'ajoutez pas de contrainte nulle après la mise à jour afin que vous ne puissiez jamais faire cela à nouveau.