Бинарный поиск или обновление индекса Btree - PullRequest
4 голосов
/ 30 октября 2008

Представьте, что вам ежедневно вручают новую книгу от автора. Книга находится в стадии разработки. Он не говорит вам, что он изменил или добавил.

Ваша задача - определить изменения и дополнения и передать их ТОЛЬКО издателю (у которого нет времени читать всю книгу каждый день)

Для решения этой проблемы книга состоит из 1 млн строк текста ascii и растет (фактически это файл резервной копии MySQL).

Моя текущая идея - создать безопасный хеш (например, SHA256) для каждой строки (1 тыс. Символов) и сохранить его на HD. Поскольку размер хеша составляет всего 32 байта, размер файла составляет всего 32 МБ.

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

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

Для сравнения используется двоичный метод поиска сравнения строк (> <операнды) Это возвращает результат в среднем за четыре итерации. </p>

Я еще не кодировал решение для индекса btree, но как бы вы справились с этим?

Ответы [ 6 ]

1 голос
/ 30 октября 2008

Я бы использовал diff .

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

0 голосов
/ 31 октября 2008

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

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

Ссылка "diff" выводит меня на страницу с описанием того, что я предполагаю, является приложением? Нет ссылки на скачивание, нет кода на любом языке ... Что мне здесь не хватает?

Некоторые из вас говорили о гранулярности уровня байтов. Это не нужно. требуется только гранулярность на уровне строки, потому что если что-либо в строке было изменено, вся строка (запись) должна быть обработана повторно, так как любое изменение в строке влияет на всю строку.

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

Таким образом, используя безопасный хеш, такой как SHA256 (MD5 имеет коллизии и по сравнению с ним медленнее), я могу обрабатывать около 30 МБ / с на своем ноутбуке HO. Сервер, конечно, будет проходить через него намного быстрее.

Таким образом, если файл имеет 1 ГБ, создание всех файлов занимает около 33 секунд, а чтение файла 1 ГБ с использованием памяти страниц Windows занимает около 30 секунд. Не ужасно

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

Имейте в виду, что книга строк (устаревшая база данных) неизвестна во всех аспектах. Нет гарантии порядка строк, местоположения изменений, типа изменений.

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

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

Это наиболее актуально здесь: По мере того, как мы переходим в область хранения терабайтных данных, возможность перестраивать хранилище данных с нуля по ночам пойдет по пути динозавра. Логический и эффективный подход к обновлению хранилища данных включает некоторую форму стратегии постепенного обновления.

Так что, я думаю, я на правильном пути? Индекс btree не позволил бы получить преимущество?

0 голосов
/ 30 октября 2008

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

Вам нужен алгоритм хеширования с очень широким ключом, так как этот подход уязвим для атак на день рождения . MD5 или любой из семейства SHA было бы хорошо. Он также не может обнаружить удаления без постобработки, которая проходит через различие в поисках отсутствующих естественных ключей. Это вычисление действительно должно знать структуру таблицы.

0 голосов
/ 30 октября 2008

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

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

также, вы должны признать переупорядочения? или только вставки / удаления / замены?

наиболее общий случай - это полный алгоритм rsync, который выглядит следующим образом:

  • определение параметров:

    1. выберите размер блока 512, или 1к обычно работают нормально.
      • выберите «сильную» контрольную сумму. что-то вроде MD4 или около того. 64 бита много.
      • выберите «слабую» скользящую контрольную сумму. тот, который позволяет вам «вычесть» хвостовой байт и «добавить» главный байт, чтобы получить контрольную сумму блока на 1 байт вперед. обычно 16-битная контрольная сумма работает нормально.
  • подпись старого файла:

    1. пройти весь старый файл, в каждом блоке вычислять как слабые, так и сильные контрольные суммы. с контрольными суммами 16 и 64 бит и блоками по 512 байт, что означает 10 байт на блок или 20 КБ на мегабайт. это «подпись»
  • создать «патч» с новым файлом и подписью старого файла:

    1. загрузить сигнатуру старого файла, лучше всего использовать хеш-таблицу со слабыми контрольными суммами в качестве ключей, сильные контрольные суммы и положение блока являются значениями.
      • прочитать первый блок нового файла
      • вычислить слабую контрольную сумму загруженного блока
      • проверьте хеш-таблицу, чтобы увидеть, есть ли слабая контрольная сумма.
      • если найдено, вычислите сильную контрольную сумму и сравните с найденной в хэше
      • если обе контрольные суммы совпадают, пометьте как «получил» ссылку на блок в хэше, продвиньтесь на один полный размер блока и вернитесь к шагу 3
      • если сильная контрольная сумма не совпадает или если слабая контрольная сумма отсутствует в хэше, «свернуть» слабую контрольную сумму, то есть «добавить» следующий байт после блока и «вычесть» первый байт из хвоста.
      • добавить байт «вычтенный» из хвоста в список «новых» байтов в патче
      • вернуться к шагу 4
  • применить исправление к старому файлу

    1. 'patch' - это список 'новых' байтов, которые выпали при проверке контрольной суммы, плюс список блоков 'has it', которые совпадают со старым файлом.
0 голосов
/ 30 октября 2008

Книга из 1 миллиона строк огромна: возможно, 30-50 строк на страницу, поэтому давайте будем щедрыми и предположим, что 100 строк на страницу, что означает 10000 страниц в книге.

Строки размером 1 КБ также намного больше, чем обычно; Базовая читаемость предполагает, что рядом не так много символов в строке. Намереваетесь ли вы хэшировать строки размером до 1 КБ или разбивать файл на фрагменты размером 1 КБ? Одна проблема с вашей схемой состоит в том, что любые повторяющиеся строки будут иметь повторяющийся хеш; Вы никогда не сможете определить, когда одна из этих строк была добавлена ​​или удалена.

Вы, вероятно, должны также уведомить издателя об удаленных строках.

Как и в случае с Glomek, я бы использовал diff для файла. Если вы сохраните файл под управлением RCS или CVS, у вас будет только текущая версия файла и различия между предыдущими версиями. При этом вы сможете создавать кумулятивные различия за неделю или месяц.

И я, вероятно, не стал бы разрабатывать свою собственную индексацию B-Tree.

0 голосов
/ 30 октября 2008

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

Понял: 1 млн строк сегодняшних значений хеш-функции по сравнению с 1 млн строк вчерашних значений.

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

Если есть добавления или удаления, вам придется использовать алгоритм diff, чтобы определить масштаб изменения.

Все в порядке. Не слишком сложно для реализации.

В этом контексте следующее не имеет смысла.

Для сравнения используется бинарный поиск метод сравнения строк (> < операнды) Это возвращает результат в среднее из четырех итераций.

Есть ли какое-то упорядочение хеш-значений? Или какая-то древовидная структура?

...