Moyen efficace de mise à jour de toutes les lignes dans une table
J'ai une table avec un grand nombre d'enregistrements (peut être plus de 500 000 ou 1 000 000). J'ai ajouté une nouvelle colonne de ce tableau et j'ai besoin de remplir une valeur pour chaque ligne dans la colonne, à l'aide de la ligne correspondante de la valeur d'une autre colonne de ce tableau.
J'ai essayé d'utiliser des transactions distinctes pour la sélection de chaque segment suivant de 100 dossiers et mise à jour de la valeur pour eux, mais tout cela prend des heures pour mettre à jour tous les enregistrements dans Oracle10 par exemple.
Quel est le moyen le plus efficace de le faire en SQL, sans utiliser un dialecte de fonctionnalités spécifiques, de sorte qu'il fonctionne partout (Oracle, MSSQL, MySQL, PostGre, etc.)?
Informations SUPPLÉMENTAIRES: Il n'y a pas de champs calculés. Il y a des indices. Utilisé instructions SQL générées par la mise à jour de la table ligne par ligne.
- Peu de gens goto à l'extrême de l'disabiling
INDEX
es si présent sur la mise à jour/instered colonne, et de laisser le travail de nuit pour les analyses qu'il. - Nous avons besoin de plus d'informations. Dites-nous sur le schéma de la table... tout "calculé" colonnes? Les index? 500k - 1m de lignes n'est PAS un grand nombre d'enregistrements par un tronçon.
- Merci à tous pour la réponse rapide. J'ai sauté la partie que je suis en utilisant les instructions SQL générées. Maintenant j'ai regardé profondément en elle et il semble que le SQL généré des mises à jour, ligne par ligne! De sorte que toute tentative de séparer en morceaux de 100 dossiers a pas de sens... je vais changer le code pour générer une bonne instruction SQL UPDATE, comme dans la accepté de répondre.
Vous devez vous connecter pour publier un commentaire.
La manière habituelle est d'utiliser la mise à JOUR:
Vous devriez être capable de faire cela est d'une transaction unique.
Marcelo suggère:
Si cela prend trop de temps et échoue en raison d'un "instantané trop vieux" erreurs (par exemple, si l'expression de requêtes un autre très actif, table), et si la nouvelle valeur de la colonne est toujours PAS NULL, vous pouvez mettre à jour la table en lots:
Il suffit d'exécuter cette instruction, de valider, puis de l'exécuter à nouveau, rincer, répéter jusqu'à ce qu'il rapporte "0 lignes mises à jour". Ça va prendre plus de temps, mais chaque mise à jour est moins susceptible d'échouer.
EDIT:
Une meilleure solution qui devrait être plus efficace est d'utiliser le
DBMS_PARALLEL_EXECUTE
API.Exemple de code (à partir d'Oracle docs):
Oracle Docs: https://docs.oracle.com/database/121/ARPLS/d_parallel_ex.htm#ARPLS67333
Vous pouvez déposer n'importe quel index sur la table, puis faites de votre insert, puis de les recréer les index.
Peut ne pas fonctionner pour vous, mais une technique que j'ai utilisé une couple de fois dans le passé pour des circonstances similaires.
créé updated_{table_name}, puis sélectionnez insérer dans ce tableau en lots. Une fois terminé, et ceci repose sur Oracle ( qui je ne sais pas ou l'utilisation ) d'appui à la possibilité de renommer les tables dans une atomique de la mode. updated_{table_name} devient {table_name} en {table_name} devient original_{table_name}.
Dernière fois que j'avais à faire c'était un très indexé table avec plusieurs millions de lignes absolument positivement pourrait ne pas être enfermé pour la durée nécessaire pour apporter des changements importants à elle.
Quelle est la version de base de données? Découvrez les colonnes virtuelles en 11g:
Ajout de Colonnes avec une Valeur par Défaut
http://www.oracle.com/technology/pub/articles/oracle-database-11g-top-features/11g-schemamanagement.html
mise à jour des Hôtels de Réduction=30 où Hotelid >= 1 et Hotelid <= 5504