Mise à jour de 700 millions de lignes avec la même valeur


12

J'ai un entrepôt de données (oracle) où je dois définir une colonne à la même valeur pour les 700 millions de lignes.

Je n'ai pas d'accès administrateur, ni accès à un administrateur, donc cela doit être accompli avec sql de base et aucune table temporaire ne crée.

Pour compliquer encore les choses, si j'essaie de faire une simple mise à jour où 1 = 1, il manque d'espace de rétablissement.

La façon dont je le fais fonctionner en ce moment est en boucle comme ceci:

loop
  update mytable set mycolumn = '1' where mycolumn is null and rownum < 50000;
  commit;
end loop

mais je sais que c'est probablement naïf et il doit y avoir une solution plus rapide et plus élégante.


La table est-elle partitionnée?
Jack dit d'essayer topanswers.xyz

Je ne le crois pas. Il existe quelques index, mais aucun ne concerne la colonne que je mets à jour.
owook

Réponses:


4

Si vous avez l'espace, vous pouvez utiliser CTAS en utilisant un minimum d'annulation / de rétablissement . Si vous avez des index, le faire d'une autre manière sera très lent et générera une journalisation comme un fou.

Dans le cas où vous avez un seul IOT sans index secondaire, ou un cluster de table unique, vous pouvez parcourir la mise à jour de la clé primaire / cluster en morceaux sans avoir à analyser à nouveau la table entière pour trouver les champs qui n'ont pas encore été mis à jour.

--Éditer

Je ne suis pas en mesure de créer une table secondaire ... Il y a quelques index, mais aucun ne concerne la colonne que je mets à jour.

Ensuite, je suggère de diviser le tableau en morceaux pour le traitement en utilisant quelque chose sur lequel vous indexez (même s'il s'agit d'une seule colonne, vous pouvez le diviser en plages de valeurs) Cela fera un FTS une fois au lieu d'une fois pour chaque morceau comme dans votre code. Vous devrez vivre avec beaucoup de refaire et effacer votre espace d'annulation aussi (donc pas de flashback par la suite)

--edit2

si vous pouvez ajouter / renommer / supprimer des colonnes, vous pouvez le faire très efficacement , mais uniquement sur 11g


1
Si votre DBA vous le permet NOLOGGING, cela invalidera les hotstandbys.
Gaius

En effet, et une sauvegarde par la suite serait également une bonne idée - mais il s'agit d'un entrepôt et d' nologgingun outil pour les entrepôts
Jack dit d'essayer topanswers.xyz

Je ne suis pas en mesure de créer une table secondaire, certainement pas aussi grande que la première, même si elle n'est que temporaire.
owook

Votre lien 11g semblait prometteur, mais je vois des commentaires là-dedans que pour une table de 60 m, il était toujours horriblement lent car il fallait définir la valeur pour chaque ligne. Étant donné que ma table fait 10 fois cette taille, cette méthode n'est peut-être pas une amélioration.
owook

@owook no, sur 11g, cette opération est rapide et ne définit pas la valeur pour chaque ligne "pour certains types de tables (par exemple, les tables sans colonnes LOB)" . Essayez-le sur un sous-ensemble de votre table ( create table foo as select * from bar where rownum<100000)
Jack dit essayez topanswers.xyz

1

Si vous êtes sur 11g, déposez la colonne et ajoutez-la en tant que colonne NOT NULL avec une valeur par défaut. C'est contre-intuitif, mais Oracle stockera la valeur par défaut dans la définition de la table, en la remplaçant au moment de l'exécution.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.