О таблицах
11.04.2011 23:05:45И ведь задача простая. Требуется структурировано хранить табличку. Всего-то на восемь столбцов. В неё надо регулярно писать. Периодически надо читать, причём, здесь нужна возможность параметризованной по столбцам выборки. Иногда надо обновлять одно поле. Иногда удалять записи. В общем-то, и всё. А поди ж ты, проблема!
На сегодня для решения этой задачи используется SQLite. Разумеется, третьей версии, разумеется, с транзакциями (иначе писать много невозможно). SQLite здесь кажется ну очень подходящей вещью, всё-таки хоть и куцый, но вполне себе SQL, ресурсов кушает минимум, писать просто, отличные возможности выборки, на одну табличку, тем более, безо всяких индексов, всяко должно хватать. И его действительно более-менее хватает пока база данных не превышает, скажем, 50 мегабайт. Как только она начинает зашкаливать за 100-200-300 — работать становится невозможно.
Основная проблема в сочетании записи и выборки. Используются для этого разные процессы и для записи приходится начинать транзакции типа EXCLUSIVE, иначе возможны ошибки при выполнении COMMIT, а их разумно решить крайне сложно. При этом, естественно, никакая выборка данных, в то время как база открыта эксклюзивно для другого процесса, невозможна.
С одной стороны, таймаут на запись небольшой и можно подождать, но, похоже, при росте базы процесс коммита начинает занимать всё больше и больше времени, плюс, поток на запись может сам по себе быть довольно плотным и времени между транзакциями может быть совсем немного.
С другой стороны, как только у чтеца появляется возможность залочить базу под себя, он её радостно берёт и… жуёт в течение этак полуминуты. Ладно ещё что это так много времени занимает, понятно, что индексов нет (иначе очень сильно деградирует запись), что в памяти базы нет и приходится её жевать полностью в прямом эфире. Но ведь, при этом невозможна никакая запись, а это уже не просто неприятно, тут можно дожить до переполнения буферов писателя и какие-то записи просто потерять!
Ближайшее простое решение видится исключительно в русле наращивания мускулов движка SQL, переход, например, на Drizzle или Firebird. Всё бы ничего, но разница в требуемых ресурсах измеряется кратно, этак на порядок, а ведь всё это хозяйство должно радостно работать не только на мощных машинках, но и на каких-нибудь чудесах об 500 МГц и 256 Мб памяти.
Конечно, пробовал найти какие-то альтернативы для подобного рода структурированного хранения, но не получилось. BerkeleyDB оперирует key->value, а больше ничего серьёзного для такого рода вещи не видно в принципе. Конечно, есть подозрение, что на уровне базы в виде файла, который открывается разными процессами с разными целями, проблема не решаема, поскольку если у читателя не будет возможности работать со своей стабильной копией, писатель обязательно найдёт способ ему нагадить.
С другой стороны, если взять какой-нибудь простецкий формат записи типа CSV, то, пожалуй, проблема читателей-писателей будет отсутствовать, но, появится проблема с адекватной по скорости выборкой, плюс с обновлением и, особенно, удалением записей.
Неужели придётся городить свой огород?
12.04.2011 01:19:55
Интересная проблема… а можно поинтересоваться что за данные?
Выборка по каким полям идет?
Если несколько приложений набрасываются на один файл — это конечно узкое место… может быть написать специальный сервис, который откроет базу себе и больше никому ее не даст, а остальные пусть асинхронно через него ходят. 🙂
12.04.2011 08:46:26
Да нехитрые, в общем, данные, несколько столбцов описательных (как числовых, так и текстовых, произвольных), один содержательный, можно сказать, так. Выборка всего, но параметры чисто «описательные», типа «дай-ка всё, что имеет в столбце 4 ‘KFUvndua'» или «давай сюда всё, что в столбце 2 от 868 до 14830».
По настоящему хорошо было бы как в нормальных базах, когда читатель работает, по сути, со своей копией, а писатель в то же самое время пишет куда-то в свою. И только после коммита представление базы у читателя меняется на новое, притом, между его транзакциями. И получается, что никто никого не ждёт, всё прекрасно. Но это очень уж жирно выходит по ресурсам.
13.04.2011 09:41:47
Вообще, насколько помню, есть embedded-вариант firebird как раз для таких случаев, когда не надо пускать сам сервак СУБД. Жрёт она немного, работает вполне шустро. Ещё для JAVA есть hsqldb, пробовал, для небольших баз годится.
Индексы всё же рекомендовал бы построить хотя бы по некоторым полям, так как база всё равно небольшая, а сэкономить на чтении это поможет.
13.04.2011 09:48:56
Не-не-не, жаба-дотнетов там нет, не будет и не может быть. А вот Embedded Firebird, наверное, так или иначе посмотрим.
Индексы, по крайней мере, на SQLite _очень_ сильно просаживают запись в нашем случае, поэтому, пока без них. Чтение реально не так критично по времени, здесь много важнее всё вовремя записать.