2010-08-25 4 views
6

J'ai finalement réussi à faire fonctionner mon lot d'insertion et maintenant je joue avec la taille du lot, mais je ne vois aucune différence de performance entre une valeur de 50 et une valeur de 10000. Cela semble très étrange pour moi, mais je ne sais pas ce qui se passe derrière la scène, donc ce pourrait être un comportement normal.Comment définir DataAdapter.UpdateBatchSize sur une valeur "optimale"?

J'insère 160k lignes dans une table et le temps moyen pour mes valeurs testées est de 115 +/- 2 secondes. Sans traitement par lots, il faut 210 secondes, donc je suis assez satisfait de l'amélioration. La table cible est:

CREATE TABLE [dbo].[p_DataIdeas](
    [wave] [int] NOT NULL, 
    [idnumber] [int] NOT NULL, 
    [ideaID] [int] NOT NULL, 
    [haveSeen] [bit] NOT NULL CONSTRAINT [DF_p_DataIdeas_haveSeen] DEFAULT ((0)), 
    CONSTRAINT [PK_p_DataIdeas] PRIMARY KEY CLUSTERED 
(
    [wave] ASC, 
    [idnumber] ASC, 
    [ideaID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON 
) ON [PRIMARY] 
) ON [PRIMARY] 

J'ai lu What to look for when setting UpdateBatchSize et la réponse était simplement tester deux valeurs différentes. Je peux comprendre cela, mais ne devrait-il pas être possible de calculer ou au moins de deviner une bonne valeur si vous connaissez la conception de la table, la question SQL et les données qui sont sur le point d'être insérées?

Y a-t-il des pratiques exemplaires que quelqu'un peut recommander?

Répondre

5

Vous pouvez voir l'effet du traitement par lots en consultant SQL Profiler ou en appelant le SqlConnection.RetrieveStatistics(). Ce que vous devriez voir, c'est que chaque lot correspond à un seul aller-retour à la base de données. En ce qui concerne l'optimisation de la taille du lot, une règle empirique est que les performances ont tendance à cesser de s'améliorer avec des tailles de lots supérieures à 50. En fait, des lots plus importants peuvent fonctionner plus lentement que les plus petits . Si je suis trop occupé pour tester, je commence généralement avec un lot d'environ 20 (sauf si j'utilise des paramètres de table, où les lots jusqu'à 500 peuvent être plus rapides que les plus petits). Cependant, le nombre optimal dépend de choses comme la taille totale des insertions (vont-elles toutes dans la RAM), la rapidité avec laquelle les disques se trouvent sur votre disque DB, si le journal se trouve sur un lecteur/LUN (La vitesse réalisable est généralement limitée d'abord par le nombre d'allers-retours, puis par la taille de la transaction, puis la vitesse du disque de journal (en particulier si l'accès séquentiel est possible ou s'il est forcé au hasard en raison de la concurrence avec d'autres fichiers sur les mêmes broches), et enfin RAM. Cependant, tous les facteurs sont aussi liés dans une certaine mesure. La première étape dans l'amélioration de la perf de vos insertions serait de les faire dans les transactions - peut-être une transaction par lot ou deux. Au-delà de cela, les paramètres de table évalués est probablement la prochaine étape, en utilisant une procédure stockée avec INSERT INTO Table SELECT column FROM @TableArgument.

1

Bien que la modification de UpdateBatchSize aide dans une certaine mesure, l'approche de base de l'utilisation d'un DataAdapter pour mettre à jour un grand nombre d'enregistrements va être lente. C'est parce qu'en fin de compte, une instruction SQL séparée (insérer, mettre à jour ou supprimer) sera générée par le DataAdapter pour chaque ligne. UpdateBatchSize n'affecte que le nombre de ces instructions individuelles envoyées dans un batch TSQL lorsqu'elles sont envoyées à SQL Server. Pour obtenir des améliorations beaucoup plus importantes des performances, vous souhaitez que SQLServer insère/mette à jour/supprime de nombreux enregistrements dans une seule instruction (généralement en utilisant un type JOIN). Les paramètres de la table (comme mentionné par RickNZ) sont une façon de le faire. Une autre possibilité est d'utiliser SqlBulkCopy (bien que vous ayez généralement besoin d'utiliser une table de transfert pour cela).

0

Assurez-vous qu'il existe également une transaction active qui améliorera grandement les performances (environ 30 fois dans mes tests avec MysqlDataAdapter).

Questions connexes