обнаружение, когда данные изменились - PullRequest
5 голосов
/ 19 июля 2010

Хорошо, история такая:

- У меня много файлов (довольно больших, около 25 ГБ), которые имеют определенный формат и должны быть импортированы в хранилище данных

- эти файлы постоянно обновляются данными, иногда новыми, иногда одними и теми же данными

- я пытаюсь выяснить алгоритм, как я могу определить, изменилось ли что-то для определенной строки в файле, чтобы минимизировать время, затрачиваемое на обновление базы данных

- в настоящее время он работает так, что я каждый раз отбрасываю все данные в базе данных, а затем заново импортирую их, но это больше не будет работать, поскольку мне понадобится временная метка для изменения элемента .

- файлы содержат строки и цифры (названия, заказы, цены и т. Д.)

Единственные решения, о которых я мог подумать:

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

- сохраните 2 копии файлов, предыдущие и текущие, и создайте для них diff-файлы (которые, вероятно, быстрее, чем обновление базы данных), и основываясь на них, обновите базу данных.

Поскольку объем данных очень велик, у меня пока нет вариантов. В конце концов я избавлюсь от файлов, и данные будут помещены прямо в базу данных, но проблема все еще остается.

Любой совет, будет оценен.

Ответы [ 4 ]

3 голосов
/ 19 июля 2010

Определение проблемы в понимании .

Допустим, ваш файл содержит

ID,Name,Age
1,Jim,20
2,Tim,30
3,Kim,40

Как вы указали, строка может быть добавлена ​​/ обновлена, поэтому файл становится

ID,Name,Age
1,Jim,20    -- to be discarded 
2,Tim,35    -- to be updated
3,Kim,40    -- to be discarded 
4,Zim,30    --  to be inserted 

Теперь требуется обновить базу данных, вставив / обновив только более 2 записей в два SQL-запроса или 1 пакетный запрос, содержащий два SQL-оператора.

Я делаю следующее предположения здесь

  • Вы не можете изменить существующий процесс для создания файлов.
  • Вы используете некоторую пакетную обработку [Чтение из файла - Обработка в память - Запись в БД] для загрузки данных в базу данных.

Сохранение хэш-значений Record [Name, Возраст] против идентификатора на карте в памяти, где идентификатор - это ключ, а значение - хеш [Если вам требуется масштабируемость, используйте hazelcast].

Ваша Batch Framework для загрузки данных [Опять-таки, при условии, что одна строка файла обрабатывается как одна запись], необходимо проверить вычисленное значение хеш-функции по отношению к идентификатору в памяти Map.Первое время создание также можно выполнить с помощьюваш пакетный фреймворк для чтения файлов.

 If (ID present)
--- compare hash 
---found same then discard it
—found different create an update sql 
In case ID not present in in-memory hash,create an insert sql and insert the hashvalue

Вы можете пойти на параллельную обработку, обработку фрагментов и разделение данных в памяти, используя spring-batch и hazelcast.

http://www.hazelcast.com/

http://static.springframework.org/spring-batch/

Надеюсь, это поможет.

1 голос
/ 19 июля 2010

Ну, независимо от того, что вы используете, ваш худший случай будет O (n), который на n ~ 25 ГБ данных не так хорош.

Если вы не можете изменить процесс записи в файлы.

Поскольку вы не обновляете все 25 ГБ постоянно, это ваш самый большой потенциал для экономии циклов.

1. Не пишите случайно
Почему бы вам не сделать процесс, который записывает данные, только добавлением? Таким образом у вас будет больше данных, но у вас будет полная история, и вы сможете отслеживать, какие данные вы уже обработали (что вы уже поместили в хранилище данных).

2. Сохраните список изменений, если вы должны написать случайным образом
В качестве альтернативы, если вы действительно должны делать случайные записи, вы можете сохранить список обновленных строк. Этот список может быть обработан как в # 1, и вы можете отслеживать, какие изменения вы обработали. Если вы хотите сэкономить место, вы можете сохранить список блоков, в которых изменились данные (где блок - это единица, которую вы определяете).

Кроме того, вы можете хранить контрольные суммы / хэши измененных блоков / строк. Однако это может быть не очень интересно - это не так дешево, чтобы вычислять, и прямое сравнение может быть дешевле (если у вас есть свободные циклы ЦП во время записи, это может сэкономить вам некоторое время на чтение, YMMV).

Примечание (я)

  • И # 1, и # 2 интересны, только если вы можете настроить процесс записи данных на диск
  • Если вы не можете изменить процесс, который записывает данные размером 25 ГБ, тогда я не вижу, как могут помочь контрольные суммы / хэши - вы все равно должны прочитать все данные, чтобы вычислить хэши (так как вы не знаете, что изменилось ) так что вы можете напрямую сравнить, пока вы читаете, и придумать список строк для обновления / добавления (или обновления / добавления напрямую)
  • Использование алгоритмов diff может быть неоптимальным, алгоритм diff будет не только искать измененные строки, но и проверять минимальное расстояние редактирования между двумя текстовыми файлами при определенных параметрах форматирования. (в diff это можно контролировать с помощью -H или --minimal, чтобы работать медленнее или быстрее, т. е. искать точное минимальное решение или использовать эвристический алгоритм, для которого, если iirc, этот алгоритм становится O (n log n) это не плохо, но все же медленнее, чем O (n), которое доступно вам, если вы делаете прямое сравнение построчно)
1 голос
/ 19 июля 2010

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

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

Обновление

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

0 голосов
/ 19 июля 2010

практически это проблема, которая должна быть решена программным обеспечением для резервного копирования, так почему бы не использовать некоторые из их стандартных решений? Лучше всего перехватить вызовы WriteFile, чтобы вы получали обратные вызовы при каждом обновлении. Это хорошо работает с двоичными записями.

Что-то, чего я не могу понять: файлы - это текстовые файлы, которые не просто добавляются, а обновляются? это крайне неэффективно (вместе с идеей сохранения 2 копий файлов, потому что это сделает кеширование файлов еще хуже).

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