La dégradation des performances tandis que les tables de mise à jour ayant 10s de millions d'enregistrements

dba.stackexchange https://dba.stackexchange.com/questions/17653

Question

Je veux mettre à jour les tables (mes 20-30) ayant 10s de millions d'enregistrements chacun.

Le problème est que cela prend trop de temps pour le processus de mise à jour et également à l'utilisation du processeur le temps passe très élevé. Je veux faire de telle sorte qu'il ne peut pas utiliser CPU beaucoup plus lors du traitement des données. Si le temps de traitement augmente alors il ne sera pas un problème pour moi, mais il devrait utiliser les ressources limitées du processeur pour le traitement (mise à jour) la table. J'utilise PostgreSQL comme base de données et système d'exploitation du serveur est Linux.

query Exemple de mine peut être comme ça

UPDATE TEMP 
SET CUSTOMERNAME = 
  ( select customername from user where user.customerid = temp.customerid );
Était-ce utile?

La solution

La première question est: Pourquoi est-il important que vous n'utilisez pas beaucoup de temps CPU? La requête sera sur un goulot d'étranglement certains ressources; si vous pouvez introduire un accès suffisant disque supplémentaire, le temps CPU utilisé par seconde descendrais, mais serait-ce vraiment une amélioration? Quelles sont les ressources préféreriez-vous sature? Comprendre pourquoi vous avez mis l'accent sur ce guide aide les gens à la force de donner une réponse que vous trouverez utile.

Comme le suggère un commentaire, votre requête peut courir plus vite avec une jointure plutôt qu'un sous-requête corrélée. Quelque chose comme ceci:

UPDATE temp
  SET customername = user.customername
  FROM user
  WHERE user.customerid = temp.customerid;

Une autre chose importante à savoir est de savoir si vous souhaitez mettre à jour toutes les lignes de la table. Quelques-unes des valeurs déjà correcte? Si oui, vous obtiendrez un gain important de performances en ne mettant à jour les lignes qui ne ont pas besoin. Ajouter AND temp.customername is distinct from user.customername à la clause WHERE.

Si vous limitez le nombre de lignes mises à jour dans chaque état, et VACUUM ANALYZE après chaque mise à jour, vous éviterez la table ballonnement. Si le point de la volonté de minimiser le temps CPU est d'éviter un impact sur les performances des transactions simultanées, cela vous donne l'occasion de présenter un court délai (sous la forme d'un sleep ou quelque chose de similaire) avant de commencer la prochaine UPDATE d'un ensemble de lignes.

Mieux encore, pourquoi êtes-vous stockez les informations contenues dans redondance de la table temporaire plutôt que de se joindre à lui en cas de besoin? (Parfois, il y a une bonne raison,. Il est très souvent pas)

Autres conseils

Si vous suivez les très bons conseils de kgrittn et ont encore des problèmes de performance, vous devrez peut-être effectuer la mise à jour par lots. Vous encore effectuer des mises à jour sur la base-set mais les limiter aux 1000 premiers (ou quel que soit le numéro qui vous convient, j'ai utilisé de 500 à 50 000) des documents qui ne correspondent pas et tourne en boucle jusqu'à ce que tous sont faites.

S'il y a un index sur TEMP.CUSTOMERNAME et vous mettez à jour une partie importante de la table TEMP puis déposez cet index avant la mise à jour et la reconstruction après.

PostgreSQL n'a aucun moyen de réduire la quantité de temps CPU d'un processus peut utiliser. Sous Linux, vous pouvez utiliser des fonctionnalités telles que OS renice commande pour le faire. Voir les priorités pour plus d'informations et des échantillons.

scroll top