Комментарии 54
Добавил в закладки. Жду продолжения :)
покрытие кода тестами 100% (с августа 2009)— причем это не просто покрытие тестами, а 100% branch coverage и 100 MC/DC покрытие, и вообще цифры покрытия тут совсем не главные, их можно было гораздо меньшими усилиями достичь, чем в sqlite это сделано.
Ни в каком другом open-source проекте такой помешанности на тестах не встречал. В sqlite кода тестов в 1000+ раз больше, чем собственно кода проекта, даже с учетом того, что многие тесты написаны на более высокоуровневом Tcl. Всем рекомендую почитать www.sqlite.org/testing.html — душераздирающее чтиво :)
НЛО прилетело и опубликовало эту надпись здесь
Тагоряне. Цивилизация гипертрофированной предусмотрительности. Три четверти всех мощностей направлено у них на изучение вредных последствий, каковые могут проистечь из открытия, изобретения, нового технологического процесса и так далее. Эта цивилизация кажется нам странной только потому, что мы не способны понять, насколько это интересно — предотвращать вредные последствия, какую массу интеллектуального и эмоционального наслаждения это дает. Тормозить прогресс так же увлекательно, как и творить его, — все зависит от исходной установки и от воспитания. В результате транспорт у них только общественный, авиации никакой, зато прекрасно развита проводная связь. © Аркадий и Борис Стругацкие. Волны гасят ветер
Про WAL очень даже интересно было бы почитать. Спасибо за статью.
SQlite позволяет занести в этот столбец значения любого типа (999, «abc», «123», 678.525).
Если вставляемое значение — не целое, то SQlite пытается привести его к целому.
какой кошмар…
много встроенных функцийпо ссылке 40 функций, включая перегруженные варианты. Это хорошо или необычно?
В чем кошмар такого подхода с типами?
По поводу функций, в принципе данного более чем достаточно в повседневной жизни. Если есть необходимость в какой-то специфичной, то можно сделать легко и просто свою функцию, зарегистрировать ее и вызывать уже в SQL запросах, таким образом наращивать функциональность можно столько сколько необходимо.
Например можно реализовать сортировку сложных структур хранящихся в BLOB полях.
По поводу функций, в принципе данного более чем достаточно в повседневной жизни. Если есть необходимость в какой-то специфичной, то можно сделать легко и просто свою функцию, зарегистрировать ее и вызывать уже в SQL запросах, таким образом наращивать функциональность можно столько сколько необходимо.
Например можно реализовать сортировку сложных структур хранящихся в BLOB полях.
Кошмар как минимум в том, что этот подход сразу больно пинает по производительности
На самом деле на уровне SQLite API можно явно указывать, с каким типом работаешь в каждом поле, в этом случае не потребуется не только автоконвертации, но и вообще конвертации чисел в текст в процессе основной работы (не считая, конечно, вывода итогов пользователю). Это если использовать биндинг полей.
Дело не только в конвертации, а еще и в самом хранении таких полей. По сути мы для каждой ячейки должны хранить некий variant — т. е. идентификатор типа и сами данные, которые при вычитывании конвертить.
Что есть ячейка, поле или запись? Для полей тип данных задан в виде семантической информации, но он никак не влияет на способ хранения, только на то как данные будет представлять редактор и компилятор запросов (т.е. к какому типу приводить на автомате). Таким образом любое BLOB поле можно рассматривать как набор бинарных данных, либо как конкретное значение в зависимости от контекста.
Например у себя в одном проекте в поле храню все начиная от просто чисел, заканчивая изображениями. При построении точно знаю какие значения в поле будут находится и уже использую явное указание типа. С тем же успехом можно вычитать бинарные данные и скастовать их в то что нужно.
PS рассуждаю с точки зрения C/C++, в других языках не работал с SQLite.
Например у себя в одном проекте в поле храню все начиная от просто чисел, заканчивая изображениями. При построении точно знаю какие значения в поле будут находится и уже использую явное указание типа. С тем же успехом можно вычитать бинарные данные и скастовать их в то что нужно.
PS рассуждаю с точки зрения C/C++, в других языках не работал с SQLite.
Да, тип поля, конечно, хранится в БД. Структура файла SQLite хорошо документирована — www.sqlite.org/fileformat.html Типы нужны для 1) конвертации в читабельное состояние при выводе результатов, 2) в SQL-функциях над несовместимыми типами производится конвертация (ну то есть если к строке прибавлять число, то оно конвертируется в число, а не в виде blob'а пристыковывается). Но при операциях над одним типом (наиболее массовые операции — всякие там SUM и прочая арифметика) никакой конвертации, поэтому не ухудшает производительность.
>В чем кошмар такого подхода с типами?
Кошмар не кошмар, но вызывает иногда трудно диагностируемые глюки. Например, в редакторе БД вставляешь значение, а оно записывается не как 1, а как «1» и потом выборка Where someRow=1 возвращает тебе пустоту.
Кошмар не кошмар, но вызывает иногда трудно диагностируемые глюки. Например, в редакторе БД вставляешь значение, а оно записывается не как 1, а как «1» и потом выборка Where someRow=1 возвращает тебе пустоту.
С записью/чтением никогда не было проблем, работаю через Qt обертку и стараюсь использовать prepared statements.
Бывает поля делаю с типом BLOB (читай не типизированные), тогда где необходимо явное приведение типа использую уже CAST.
Бывает поля делаю с типом BLOB (читай не типизированные), тогда где необходимо явное приведение типа использую уже CAST.
Работаю с SQLite больше 7 лет, никогда с таким не сталкивался. Наверняка это особенность конкретного редактора БД, а не собственно SQLite.
>В чем кошмар такого подхода с типами?
Сконвертировал/симпортил кривой excel файл и получи на выходи черт пойми какие результаты запросов (все ведь проглотится). Вы в курсе, какие выкрутасы, например, PHP вытворяет при сравнении переменных? Явное, оно, как известно, лучше неявного.
Сконвертировал/симпортил кривой excel файл и получи на выходи черт пойми какие результаты запросов (все ведь проглотится). Вы в курсе, какие выкрутасы, например, PHP вытворяет при сравнении переменных? Явное, оно, как известно, лучше неявного.
>> по ссылке 40 функций, включая перегруженные варианты. Это хорошо или необычно?
Это в особенности. Стандарта на функции в SQL, как понимаю, не существует.
Это в особенности. Стандарта на функции в SQL, как понимаю, не существует.
Ну почему, постгресовцы пишут, что кое-что в стандарте есть: www.postgresql.org/docs/9.1/interactive/functions-string.html#FUNCTIONS-STRING-SQL
НЛО прилетело и опубликовало эту надпись здесь
В 2000ом году в качестве халтурки написал биллинг для АТС на 10тыс абонентов, всё это было на Linux, интерфейс через CGI. Тогда использовал Interbase 4 который мог работать без сервера, просто линуешься с библиотекой и она сама открывает файл, ну прямо в точности как SQLlite сегодня. Единственное большое отличие, Interbase реализовывал изоляции транзакций и позволял нескольким процессам писать, использовались средства IPC для синхронизации между несколькими процессами работающими с одной и той же БД, сервера же выделенного при том нет.
Кстати, если вся мощь SQL не особо нужна, а просто ключ-значение, то можно использовать Berkeley DB, который позволяет несколько писателей одновременно, тоже кросс платформенный, на C.
Спасибо. Как раз для меня статья)
Вот про это хотелось бы почитать.
b) можно без труда организовать БД в памяти (это очень удобно и чуть позже расскажу подробнее);
Вот про это хотелось бы почитать.
Неоднократно приходилось использовать SQLite. Всегда оставался доволен. Правда возникали проблемы с синтаксисом команд, он был несколько отличен от привычного мне MySQL, но решения быстро находились. К сожалению, это было давно и конкретные примеры привести не смогу.
Использовал SQLite в одном своем проекте, напоролся на неприятную вещь. Мне приходилось писать в базу часто и маленькими порциями, происходило все это на панельном PC у которого в качестве диска использовалась Compact Flash, так вот по истечении некоторого времени работы приложения (примерно месяц) слетала файловая система, я достаточно много времени потратил на поиск проблемы, и до сих пор на 100% не уверен что я ее нашел, но после того как нашел описанное ниже и устранил приложение работает уже около полу года, так вот, у Sqlite по умолчанию включено ведение журнала, и журнал этот ведется следующим образом — перед началом транзакции создается файл журнала, производится запись в базу, журнал удаляется, и так при каждой транзакции, у меня это происходило где-то раз в секунду. Как известно для удаления файл просто помечается в таблице размещения что он удален, то-есть производилась операция записи в одно и тоже самое место. На обыкновенном HDD такое поведение не вызвало бы никаких проблем, но на флеше это приводило к порче носителя(колличество циклов записи флеш памяти — 10е6 раз), когда вы пишете на нее данные она пишется циклично и одна и таже ячейка не модифицируется постоянно, в моем же случае происходила именно модификация одной и той же самой ячейки, что приводило к сбою. Вот так вот коварно…
«устранил»
Что именно вы сделали, подскажите? Отключили журнал? А бэкап прикрутили потом? Или уже был?
Что именно вы сделали, подскажите? Отключили журнал? А бэкап прикрутили потом? Или уже был?
Отключил ведение журнала и написал скрипты востановления базы, база Sqlite, если в ней возникли проблемы, может быть считана до того места где эта проблема возникла, меня это устраивало. Бекапить в поле некуда. :)
> база Sqlite, если в ней возникли проблемы, может быть считана до того места где эта проблема возникла,
Можете чуть подробнее об этом рассказать? очень интересно.
Можете чуть подробнее об этом рассказать? очень интересно.
Если SQLite база сбоит (обычные команды открытия/чтения базы дают ошибку SQLITE_CORRUPT), то часто все-равно можно сделать «sqlite .dump» через консоль, получить все данные (в виде команд insert) до сбойного места. Ну как в MySQL в случае myisam можно частично восстановить табличку после сбоя.
Можно было не отключать ведение журнала, а вести его в памяти:
PRAGMA journal_mode = MEMORY
И тем самым сохранить возможность делать ROLLBACK.
PRAGMA journal_mode = MEMORY
И тем самым сохранить возможность делать ROLLBACK.
sqlite — безусловно хорошая штука. Пользовался ей в нескольких проектах, единственное что огорчает — отсутствие враппера для С++ в стандартной поставке, в результате их пишут все кому не лень (да и чего скрывать — я тоже свой писал, т.к. не нашел подходящего под свои требования). А без враппера юзать sqlite не очень удобно, в плюсах разумеется.
Хороших врапперов мало, но я не так давно стал использовать Poco::Data и остался очень доволен. Все в стиле с++, очень хорошо ложится в проект.
в контексте SQLITE меня убивают вещи типа «sqlite-server»
люди СПЕЦИАЛЬНО делали встраиваимою базу данных
так надо поверх нее сделать клиент сервера…
причем с завидным упорством…
p.s. а уж в где только SQLITE не используется, даже вон в Adobe Light Room
люди СПЕЦИАЛЬНО делали встраиваимою базу данных
так надо поверх нее сделать клиент сервера…
причем с завидным упорством…
p.s. а уж в где только SQLITE не используется, даже вон в Adobe Light Room
Ну а что удивительного? Есть отлично работающая база и возникает задача одновременного доступа из нескольких приложений.
И не хочется все бросить и ставить Oracle, если можно придумать как обойтись SQLite ;-)
И не хочется все бросить и ставить Oracle, если можно придумать как обойтись SQLite ;-)
ага, и как результат — получим недо mySQL/etc
у этого проекта есть идея — быть локальной базой
нужны сетевые — их есть
у этого проекта есть идея — быть локальной базой
нужны сетевые — их есть
Дык мускуль на что? :-)
На самом деле SQLite3 и так позволяет нормальный параллельный доступ из разных процессов и из разных потоков к одним и тем же БД, не требуется ничего наворачивать сверху, SQLite сам разбирается со всеми блокировками, кэшами и т.п. В частности, это очень активно используется в Eserv (отечественный почтовый и веб сервер), начиная с 4й версии (индексы писем и пр.).
Наиглавнейшее достоинство SQLite — переносимость. За это ей можно было бы простить все что угодно. А уж то что она сама по себе неплоха и вовсе замечательно.
Мне вот единственное что мешает — отсутствие редактируемых вьюх.
Я как-то редко использую view. Может и зря. А зачем их редактировать?
Скажем, в моем случае:
1. Есть БД. Делается запрос со всякими джойнами и кладется в табличное представление.
2. В табличном представлении пользователь что-то меняет.
3. Апдейтится БД.
Через View пункт 3 делается с пол тычка. Без этого же приходится писать промежуточную модель данных с таблицей и расшифровкой каждого ее столбца — из какой таблицы/столбца БД взяты эти данные. Иначе непонятно, куда записывать изменения.
1. Есть БД. Делается запрос со всякими джойнами и кладется в табличное представление.
2. В табличном представлении пользователь что-то меняет.
3. Апдейтится БД.
Через View пункт 3 делается с пол тычка. Без этого же приходится писать промежуточную модель данных с таблицей и расшифровкой каждого ее столбца — из какой таблицы/столбца БД взяты эти данные. Иначе непонятно, куда записывать изменения.
То есть базы которые update view сразу занесут сами в несколько таблиц? Не знал. Круто.
Как минимум MS умеет это делать msdn.microsoft.com/en-us/library/ms180800.aspx
Как вариант, можно использовать INSTEAD OF триггер для изменения/удаления/вставки и самому реализовать необходимую логику. (применимо для MS/Oracle/PostgreSQL)
Получил очень неприятный опыт. Как оказалось, SQLite некорректно обрабатывает запросы с выборками дат. Выяснилось в самый последний момент.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
SQLite — замечательная встраиваемая БД (часть 1)