2009-06-19 8 views
0

J'ai une source de données qui fournit une liste d'objets et leurs propriétés (un fichier CSV, mais cela n'a pas d'importance). Chaque fois que mon programme s'exécute, il doit extraire une nouvelle copie de la liste des objets, la comparer à la liste des objets (et leurs propriétés) stockés dans la base de données et mettre à jour la base de données si nécessaire.Algorithme de mise à jour d'une liste à partir d'une liste

Il est facile de traiter de nouveaux objets: la source de données attribue à chaque objet un numéro d'identification séquentiel, vérifie le numéro d'ID supérieur dans la nouvelle information par rapport à la base de données et vous avez terminé. Je cherche des suggestions pour les autres cas - lorsque certaines propriétés d'un objet ont changé, ou quand un objet a été supprimé.

Une solution naïve serait de tirer tous les objets de la base de données et obtenir le complément de l'intersection des deux ensembles (anciens et nouveaux) et ensuite examiner ces résultats, mais cela semble ne pas être très efficace si les ensembles deviennent grands. Des idées?

+2

Calculer et stocker un hachage pour chaque objet? – FogleBird

Répondre

1

L'approche standard pour d'énormes piles de données équivaut à cela.

Nous supposerons que list_1 est le "maître" (sans doublons) et que list_2 est les "mises à jour" qui peuvent avoir des doublons.

iter_1 = iter(sorted(list_1)) # Essentially SELECT...ORDER BY 
iter_2 = iter(sorted(list_2)) 
eof_1 = False 
eof_2 = False 
try: 
    item_1 = iter_1.next() 
except StopIteration: 
    eof_1= True 
try: 
    item_2 = iter_2.next() 
except StopIteration: 
    eof_2= True 
while not eof_1 and not eof_2: 
    if item_1 == item_2: 
     # do your update to create the new master list. 
     try: 
      item_2 = iter_2.next() 
     except StopIteration: 
      eof_2= True 
    elif item_1 < item_2: 
     try: 
      item_1 = iter_1.next() 
     except StopIteration: 
      eof_1= True 
    elif item_2 < item_1: 
     # Do your insert to create the new master list. 
     try: 
      item_2 = iter_2.next() 
     except StopIteration: 
      eof_2= True 
assert eof_1 or eof_2 
if eof_1: 
    # item_2 and the rest of list_2 are inserts. 
elif eof_2: 
    pass 
else: 
    raise Error("What!?!?") 

Oui, cela implique un tri potentiel. Si list_1 est conservé dans l'ordre de tri lorsque vous l'écrivez dans le système de fichiers, vous gagnez un temps considérable. Si list_2 peut être accumulé dans une structure qui le garde trié, cela fait gagner un temps considérable.

Désolé pour le verbiage, mais vous devez savoir quel itérateur a soulevé le StopIteration, donc vous ne pouvez pas (trivialement) envelopper la boucle while dans un bloc big-old-try.

1

N'existe-t-il aucun moyen de conserver un champ "modifié pour la dernière fois"? C'est ce que vous recherchez vraiment: une sauvegarde incrémentielle, basée sur la dernière sauvegarde effectuée, par rapport à la dernière fois qu'un objet a été modifié/supprimé (/ ajouté).

+0

ou un champ modifié serait bien aussi! –

+0

ce serait, mais je ne suis pas la possibilité de changer la source de données CSV malheureusement ... – Dan

0

Lorsque vous placez la liste dans votre programme, parcourez la liste en effectuant une requête basée sur une propriété de colonne dans la table de base de données qui correspond à la même propriété de l'objet que la liste ObjectName. Ou vous pouvez charger toute la table dans une liste et comparer la liste de cette façon. Je suppose que vous avez quelque chose d'unique à propos de l'objet qui existe en plus de l'ID attribué par la base de données.

Si cet objet n'est pas trouvé dans la table via la requête, créez une nouvelle entrée. S'il est trouvé comme FogleBird mentionné, avoir un hachage calculé ou CRC stocké pour cet objet dans la table que vous pouvez comparer avec l'objet dans la liste (exécuter le calcul sur l'objet). Si les hachages ne correspondent pas, mettez à jour cet objet avec celui de la liste.

1

Vous devez avoir des horodatages dans votre base de données et dans votre fichier CSV. L'horodatage doit afficher les données lorsque l'enregistrement a été mis à jour et vous devez comparer les horodatages de l'enregistrement avec les mêmes ID pour décider si vous avez besoin de le mettre à jour ou non

Pour ce qui est de l'intersection ... ! Vous devez importer toutes les données de CSV dans la table temporaire et faire l'intersection entre deux tables de base de données SQL. Si vous utilisez Oracle ou MS SQL 2008 (pas sûr pour 2005), vous trouverez un mot-clé MERGE très utile, ainsi vous pouvez écrire du SQL avec moins d'efforts que vous dépenserez pour fusionner des données dans un autre langage de programmation.

Questions connexes