Nous avons une application C # qui parsing datatables des files text. Nous devons ensuite mettre à jour les loggings dans notre database sql en fonction des informations contenues dans les files text. Quel est le moyen le plus efficace de transmettre datatables de l'application au server SQL?
Nous utilisons actuellement une string délimitée, puis une boucle dans la string dans une procédure stockée pour mettre à jour les loggings. Je teste également en utilisant TVP (paramètre de table évalué). Y a-t-il d'autres options?
Nos files contiennent des milliers d'loggings et nous aimerions une solution qui prend le less de time.
Merci de ne pas utiliser de DataTable
car cela ne ferait que gaspiller du CPU et de la memory sans aucun bénéfice (autre que la familiarité). J'ai détaillé une approche très rapide et flexible dans ma réponse aux questions suivantes, qui est très similaire à celle-ci:
Comment puis-je insert 10 millions d'loggings dans les plus brefs timeouts?
L'exemple montré dans cette réponse est pour INSERT seulement, mais il peut facilement être adapté pour inclure UPDATE. En outre, il télécharge toutes les lignes dans un seul plan, mais cela peut également être facilement adapté pour définir un countur pour X nombre d'loggings et pour quitter la méthode IEnumerable après que plusieurs loggings ont été transmis, puis fermez le file une fois qu'il y a plus d'loggings. Cela nécessiterait de stocker le pointeur de file (c'est-à-dire le stream) dans une variable statique pour continuer à passer à la méthode IEnumerable afin qu'il puisse être avancé et ramassé à la position la plus récente la prochaine fois. J'ai un exemple de travail de cette méthode montré dans la réponse suivante, bien qu'il utilisait un SqlDataReader
comme input, mais la technique est la même et nécessite très peu de modification:
Comment split une grande table contenant 100 millions de données en plusieurs tables?
Et pour un peu de perspective, 50k disques n'est même pas proche de "énorme". J'ai téléchargé / fusionné / synchronisé des données en utilisant la méthode que je montre ici sur 4 millions de files de lignes et qui a frappé plusieurs tables avec 10 millions (ou plus) de lignes.
Choses à ne pas faire:
DataTable
: comme je l'ai dit, si vous le remplissez simplement dans le but d'utiliser avec un TVP, c'est un gaspillage de CPU, de memory et de time. Ce qui fonctionne, mais pas aussi flexible qu'un TVP correctement fait (c'est-à-dire en passant une méthode qui renvoie IEnumerable<SqlDataRecord>
). Ce sont ok, mais pourquoi vider les loggings dans une table temporaire juste pour avoir à les parsingr dans la destination quand vous pouvez le faire tout en ligne?
SqlBulkCopy
de .NET La meilleure façon de le faire à mon avis est de créer une table temporaire puis d'utiliser SqlBulkCopy pour l'insert dans cette table temporaire ( https://msdn.microsoft.com/fr-fr/library/system.data.sqlclient.sqlbulkcopy%28v = vs.110% 29.aspx ), puis simplement mettre à jour la table en fonction de la table temporaire.
Basé sur mes tests (en utilisant Dapper et aussi LINQ), la mise à jour en masse ou avec des lots prend beaucoup plus de time que de créer une table temporaire et d'envoyer une command au server pour mettre à jour datatables basées sur la table temporaire. Le process est plus rapide car SqlBulkCopy remplit datatables en mode natif de manière rapide, et le rest est effectué du côté du server SQL qui passe par less d'étapes de calcul, et datatables à ce stade résident à la fin du server.