Y at-il quelque chose de plus rapide que Enumerable.Except <TSource> Méthode?

J'ai un programme qui télécharge des données de database de server à la database de client. database du server continue de croître récemment.

dans ce programme, il y a une option pour sélectionner download toutes datatables ou download des données pour une période de time spécifique (peut choisir des jours en arrière à partir d'aujourd'hui). Si l'user sélectionne tout, j'ai écrit le programme pour tronquer la table de database du client et insert toutes datatables en utilisant la copy en bloc. cette partie est ok.

mais le problème est lorsque l'user choisit une période de time spécifique (chaque recode a créé l'heure des données) le programme doit comparer deux tables et split les recodes (données de server) dans deux tables. l'un est, n'existe pas de données et le second n'est pas des données existantes. et ce que je vais faire est, pas de données existantes directement insert dans DB client (j'utilise l'insertion en vrac) et l'insertion de données existantes dans une table tempory en utilisant bulkcopy et après mise à jour de la table du client en utilisant la table temporaire ci-dessus. Mon problème réel se produit lors de la division de la table du server. c'est ainsi que je l'ai fait

updateTable = (From c In dt_from_server.AsEnumerable() Join o In Dt_from_client.AsEnumerable() On c.Field(Of Ssortingng)("BARCODE").Trim() Equals o.Field(Of Ssortingng)("BARCODE").Trim() And c.Field(Of Ssortingng)("ITEM_CODE").Trim() Equals o.Field(Of Ssortingng)("ITEM_CODE").Trim() Select c).CopyToDataTable() insertTable = dt_server.AsEnumerable() .Except(updateTable.AsEnumerable(), DataRowComparer.Default) .CopyToDataTable() 

(normalement il y a plus de 1M recodes dans la table de server)

Mettre à jour la pièce en prenant un time acceptable de 10 minutes (Oui, il prend 5 Go d'espace de Ram – dans ce cas, c'est bon quand on considère la performance) mais insert des joints de pièce en jours, juste pour asservir l'insertTable (datable) . C'est le problème.
AsEnumerable().Except() partie prenant beaucoup de time et je ne pouvais pas find une solution accélérer ce process. Je ne suis pas sûr de l'avoir expliqué correctement. Quelqu'un pourrait-il me donner un conseil pour cela?

Puisque vous avez commenté que dt_from_server et dt_server sont en réalité le même DataTable vous n'avez pas besoin de comparer toutes les valeurs de tous les DataRows entre eux, ce que fait DataRowComparer.Default . Vous pouvez utiliser Except sans second paramètre pour le comparateur, alors seules les references sont comparées, ce qui est beaucoup plus rapide.

Vous n'avez pas non plus besoin de deux CopyToDataTable qui créent deux gros DataTables en memory, qui traitent les lignes les unes après les autres.

Voici une approche différente utilisant la jointure gauche-externe de Linq, qui est plus efficace:

 Dim query = from rServ in dt_from_server.AsEnumerable() group join rClient in Dt_from_client.AsEnumerable() On New With{ Key .BarCode = rServ.Field(Of Ssortingng)("BARCODE").Trim(), Key .ItemCode = rServ.Field(Of Ssortingng)("ITEM_CODE").Trim() } Equals New With{ Key .BarCode = rClient.Field(Of Ssortingng)("BARCODE").Trim(), Key .ItemCode = rClient.Field(Of Ssortingng)("ITEM_CODE").Trim() } into Group From client In Group.DefaultIfEmpty() Select new With { .ServerRow = rServ, .InsertRow = client is Nothing } Dim insertOrUpdateRows = query.ToLookup(Function(x) x.InsertRow, Function(x) x.ServerRow) Dim insertRows = insertOrUpdateRows(true).CopyToDataTable() 'CopyToDataTable redundant if you process rows immediately now' Dim updateRows = insertOrUpdateRows(false).CopyToDataTable() 'CopyToDataTable redundant if you process rows immediately now' 

Mais en général, l'approche la plus évolutive et efficace serait de ne pas charger tout en memory et de tout traiter, mais d'utiliser la pagination de database (ou une procédure stockée) pour n'en traiter que certaines parties, sinon il est probable que vous rencontrera une OutOfMemoryException tôt ou tard.


C # comme demandé:

 var query = from rServ in dt_from_server.AsEnumerable() join rClient in Dt_from_client.AsEnumerable() on new { BarCode = rServ.Field<ssortingng>("BARCODE").Trim(), ItemCode = rServ.Field<ssortingng>("ITEM_CODE").Trim() } equals new { BarCode = rClient.Field<ssortingng>("BARCODE").Trim(), ItemCode = rClient.Field<ssortingng>("ITEM_CODE").Trim() } into clientGroup from client in clientGroup.DefaultIfEmpty() select new { ServerRow = rServ, InsertRow = client == null }; var insertOrUpdateRows = query.ToLookup(x => x.InsertRow, x => x.ServerRow); var insertRows = insertOrUpdateRows[true].CopyToDataTable(); // CopyToDataTable redundant if you process rows immediately now var updateRows = insertOrUpdateRows[false].CopyToDataTable(); // CopyToDataTable redundant if you process rows immediately now