Алгоритм обновления списка из списка - PullRequest
0 голосов
/ 19 июня 2009

У меня есть источник данных, который предоставляет список объектов и их свойств (файл CSV, но это не имеет значения). Каждый раз, когда моя программа запускается, ей нужно вытащить новую копию списка объектов, сравнить ее со списком объектов (и их свойств), хранящихся в базе данных, и обновить базу данных по мере необходимости.

Работать с новыми объектами легко - источник данных присваивает каждому объекту последовательный идентификационный номер, сверяет верхний идентификационный номер в новой информации с базой данных, и все готово. Я ищу предложения для других случаев - когда некоторые свойства объекта изменились или когда объект был удален.

Наивным решением было бы вытащить все объекты из базы данных и получить дополнение к пересечению двух наборов (старого и нового), а затем изучить эти результаты, но кажется, что это будет не очень эффективно, если наборы становятся большими. Есть идеи?

Ответы [ 4 ]

1 голос
/ 19 июня 2009

Стандартный подход для огромных куч данных сводится к этому.

Предположим, что list_1 - это «мастер» (без дубликатов), а list_2 - «обновления», которые могут иметь дубликаты.

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!?!?") 

Да, это потенциальная сортировка. Если list_1 хранится в отсортированном порядке, когда вы записываете его обратно в файловую систему, это экономит значительное время. Если list_2 может быть накоплен в структуре, которая поддерживает его сортировку, то это экономит значительное время.

Извините за многословность, но вам нужно знать, какой итератор поднял StopIteration, поэтому вы не можете (тривиально) обернуть весь цикл while в большой старый блок try.

1 голос
/ 19 июня 2009

Вам нужно иметь временные метки как в вашей базе данных, так и в файле CSV. Временная метка должна показывать данные, когда запись была обновлена, и вы должны сравнить временные метки записи с теми же идентификаторами, чтобы решить, нужно ли вам ее обновлять

Что касается вашего представления о пересечении ... Это должно быть сделано наоборот! Вы должны импортировать все данные из CSV во временную таблицу и выполнить пересечение между двумя таблицами базы данных SQL. Если вы используете Oracle или MS SQL 2008 (не уверен в 2005 году), вы найдете очень полезное ключевое слово MERGE, поэтому вы сможете писать SQL с меньшими усилиями, чем потратите на объединение данных на другом языке программирования.

1 голос
/ 19 июня 2009

Нет ли способа сохранить поле «последний раз изменено»? Это то, что вам действительно нужно: инкрементное резервное копирование, основанное на последнем запуске резервного копирования, по сравнению с последним изменением / удалением (/ добавлением) объекта.

0 голосов
/ 19 июня 2009

Когда вы извлекаете список в свою программу, выполняйте итерацию по списку, выполняя запрос на основе свойства столбца в таблице базы данных, которое сопоставляется с тем же свойством объекта из списка, как ObjectName. Или вы можете загрузить всю таблицу в список и сравнить список таким образом. Я предполагаю, что у вас есть что-то уникальное в объекте, который существует помимо идентификатора, который назначает база данных.

Если этот объект не найден в таблице посредством запроса, создайте новую запись. Если он найден, как упомянуто FogleBird, имейте вычисленный хеш или CRC, сохраненный для этого объекта в таблице, который вы можете сравнить с объектом в списке (запустите вычисление для объекта). Если хэши не совпадают, обновите этот объект указанным в списке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...