#database-design #postgresql #version-control #binary #diff
#проектирование базы данных #postgresql #контроль версий #двоичный #разница
Вопрос:
Я ищу ограниченную форму контроля версий в базе данных здесь:
- Размер имеет наибольшее значение: множество ревизий одного и того же файла должно занимать как можно меньше места (я не ищу сжатия, поскольку данные уже сжаты)
- Вычислительные требования вторичны
- Я должен иметь возможность извлекать текущую ревизию документа как можно быстрее (извлечение более старых версий не критично по времени)
В основном ответы должны содержать как минимум две вещи:
- Какой алгоритм двоичного разделения вы бы использовали?
- Как бы вы структурировали эту систему специфичным для PostreSQL образом?
Ответ №1:
«Размер имеет наибольшее значение»: как насчет внешнего инструмента diff (например, bsdiff?), использующего, например, PL / sh.
«Я должен иметь возможность извлекать текущую ревизию документа как можно быстрее»: в этом случае вы захотите выполнить свой diff «неправильным» способом, поэтому каждая ревизия будет включать:
- замените ‘предыдущую ревизию’ на разницу между ‘новой ревизией’ и ‘предыдущей ревизией’
- добавить «новую ревизию»
Для возврата к старой ревизии потребуется итеративное применение предыдущих различий в виде исправлений, пока вы не доберетесь до нужной вам ревизии.
Что бы вы ни делали, я думаю, вам нужно будет сначала распаковать данные, прежде чем использовать инструмент diff. Вот почему:
dd if=/dev/urandom of=myfile.1 bs=1024 count=10
cp myfile.1 tmp; cat tmp >> myfile.1
cp myfile.1 tmp; cat tmp >> myfile.1
cp myfile.1 tmp; cat tmp >> myfile.1
cp myfile.1 tmp; cat tmp >> myfile.1
dd if=/dev/urandom of=myfile.2 bs=1024 count=10
cp myfile.2 tmp; cat tmp >> myfile.2
cp myfile.2 tmp; cat tmp >> myfile.2
cp myfile.2 tmp; cat tmp >> myfile.2
cp myfile.2 tmp; cat tmp >> myfile.2
cat myfile.1 >> myfile.2
bsdiff myfile.1 myfile.2 diff
gzip -c myfile.1 > myfile.1.gz
gzip -c myfile.2 > myfile.2.gz
bsdiff myfile.1.gz myfile.2.gz gz.diff
rm tmp
ls -l
-rw-r--r-- 1 root root 17115 2011-04-05 10:54 diff
-rw-r--r-- 1 root root 21580 2011-04-05 10:54 gz.diff
-rw-r--r-- 1 root root 163840 2011-04-05 10:54 myfile.1
-rw-r--r-- 1 root root 11709 2011-04-05 10:54 myfile.1.gz
-rw-r--r-- 1 root root 327680 2011-04-05 10:54 myfile.2
-rw-r--r-- 1 root root 23399 2011-04-05 10:54 myfile.2.gz
Обратите внимание, что это gz.diff
больше, чем diff
— если вы попробуете это с реальными файлами, я ожидаю, что разница будет еще больше.
Комментарии:
1. Спасибо за ответ: не могли бы вы, пожалуйста, пояснить, почему именно мне нужно распаковать мои данные перед использованием инструмента diff?
Ответ №2:
Мне, как правило, очень не нравится заново изобретать колесо. В случае оптимизации пространства хранения люди намного умнее меня уже нашли решения. Я бы предпочел, когда это возможно, использовать тяжелую работу этих действительно умных людей. С учетом сказанного я мог бы рассмотреть возможность хранения моих файлов в системе контроля версий, такой как Mercurial или Git, как только я пойму, как они хранят двоичные данные. Как только вы определите, какую из них вы хотите использовать, вы можете рассмотреть способы создания некоторых хранимых функций, скорее всего, на pl / perl или аналогичной, которая может взаимодействовать с системой контроля версий и преодолевать разрыв между вашими данными отношений в PostgreSQL и двоичными файлами.
Моя единственная проблема с этим подходом заключается в том, что мне не очень нравится, что я взял транзакционную систему и внедрил в нее внешнюю систему (Mercurial / Git). И вдобавок ко всему, резервная копия базы данных не будет создавать резервную копию моего репозитория Mercurial или Git. Но всегда найдется компромисс, поэтому просто определите, с какими из них вы можете смириться.