
- SQLite — самая часто разворачиваемая и используемая база данных. На текущий момент активно используется более одного триллиона (1000000000000 или миллиона миллионов) баз данных SQLite.
Её поддерживают три человека. Они не допускают внешних контрибьюторов.
- Скорее всего, SQLite используется больше, чем все остальные движки баз данных суммарно. В мире работают миллиарды копий SQLite. Её можно встретить повсюду.
- К тому же, есть такая вероятность, что это один из пяти наиболее часто разворачиваемых программных модулей.
- За разработкой SQLite стоит компания Hwaci. Кажется, она занимается и музыкой (?).
- Изначально SQLite создавалась для корабля ВМС США. Ричард Хипп (D. Richard Hipp, DRH) разрабатывал ПО для эсминца USS Oscar Austin. Раньше ПО корабля просто переставало работать при выходе из строя сервера (это было в 2000-х). Для боевого корабля это неприемлемо.
Поэтому DRH задался вопросом: что, если база данных будет работать без какого-либо сервера.
Его прямая речь:
Зачем нам вообще нужен сервер? Почему бы не считывать данные напрямую с диска? В таком случае, если компьютер достаточно мощный, он сможет выполнять наше приложение, а у нас не будет зависимостей, способных сбоить и вызывать причины сбоев. Я поискал, но не нашёл ни одного движка баз данных SQL, умеющих такое. Один из коллег тогда спросил: «Ричард, а почему бы тебе просто самому не написать его?» «Ладно, попробую». Я не сделал этого сразу, но позже возникли проблемы с финансированием. Насколько я помню, в 2000-х у Ньюта Гингрича и Билла Клинтона возник какой-то конфликт, поэтому все государственные контракты были приостановлены. На несколько месяцев я потерял работу, поэтому подумал: «Что ж, тогда я просто напишу движок баз данных».
- В отличие от большинства опенсорсных проектов, использующих стандартные лицензии (например, MIT или GPL), SQLite не поставляется с одобренной OSI лицензией.
SQLite сделали общественным достоянием (public domain), и она даже имеет ещё меньше ограничений.
Стоит также отметить, что это может стать проблемой в некоторых странах/юрисдикциях, не признающих общественное достояние. Поэтому SQLite продаёт лицензии, называемые «Warranty of Title» («гарантия чистоты прав собственности»). - Разработчики не допускают внешнего вклада в проект. Нельзя просто отправить пул-реквест и надеяться, что патч будет одобрен.
- Open Source, но не Open Contribution
Контрибьютором в SQLite можно стать только по приглашению (у меня нет ссылки на источник, подтверждающий это). Патчи можно будет добавлять только после того, как вас пригласят и вы подпишете письменное поручительство (аффидавит) о том, что передаёте свой вклад в общественное достояние. - Как там всё устроено?
На каждую строку кода SQLite приходится более 600 строк кода тестов. Тесты покрывают 100% ветвлений (и 100% MC/DC) библиотеки. Набор тестов крайне разнообразен, он включает фаззинг-тесты, тесты граничных значений, регрессионные тесты и тесты, симулирующие вылеты операционных систем, отключение питания, ошибки ввода-вывода, ошибки out-of-memory.
Изначально SQLite была расширением Tcl, а её основной набор тестов написан на Tcl. - Любопытно, что некоторые тесты SQLite проприетарны. Набор тестов TH3 (Test Harness 3), обеспечивающий стопроцентное покрытие ветвлений кода, проприетарен, а доступ к нему закрыт.
Не знаю ни одного другого проекта, который бы был открытым, но с платными тестами.
Однако разработчики не смогли продать ни единой копии TH3. DRH сказал в подкасте:
«Стопроцентные тесты MCD называются TH3. Они проприетарны. У меня была мысль, что мы можем продавать эти тесты производителям авиационного оборудования и зарабатывать на этом. Мы продали ровно ноль копий, так что затея провалилась».
Для получения доступа нужно вступить в SQLite Consortium с ежегодным членским взносом 120 тысяч долларов. - Это интересная бизнес-модель. Разработчики генерируют прибыль через лицензии, платную поддержку, сервисное обслуживание, членство в консорциуме и коммерческие расширения.
- У SQLite нет Code of Conduct (CoC), вместо него используется Code of Ethics, производный от «видов добрых дел» из главы 4 Устава святого Бенедикта.
- В SQLite вместо правовых положений благословение:
Во всех файлах исходного кода есть благословение. - SQLite настолько быстр, что конкурирует по скорости с
fopen
. В некоторых сценариях использования можно применять SQLite вместо файловой системы, это может быть на 35% быстрее.
- SQLite против Redis (угадайте, кто быстрее?)
В некоторых сценариях использования SQLite может быть быстрее, чем Redis из-за сетевого стека и лишних затрат на (де)сериализацию. - Но, в отличие от большинства баз данных, SQLite имеет модель единственного писателя. Одновременно может быть не больше одного писателя.
В 2010 году ситуация изменилась из-за добавления режима WAL. До его появления могли быть или читатели, или писатель, но не одновременно. - Есть и другие аспекты, очень часто встречающиеся в других базах данных, но не в SQLite:
- По умолчанию используется режим rollback journal, который позволяет использовать или несколько читателей, или одного писателя.
- Внешние ключи отключены; их нужно включать отдельно.
- «Слабая типизация». В SQLite это называется «аффинностью типов». Этот принцип означает, что в столбец можно вставить что угодно, даже если вы определили тип. Строгую типизацию столбцов нужно включать отдельно (при помощи опции таблиц STRICT).
- Многие команды ALTER, привычные по другим базам данных, не работают. Например, нельзя добавить ограничение к уже имеющемуся столбцу. (Недавно была добавлена возможность изменения имени столбца).
Существует целый список странностей SQLite. - Мне очень не нравится, что она не заставляет соблюдать типы. Всё полностью произвольно:
CREATE TABLE user(id INTEGER); INSERT into user VALUES ("YOLO!"); --- Это сработает!
Более того, база данных не выбрасывает никаких ошибок, если передать ей какой-то произвольный тип.
CREATE TABLE t(value TIMMYSTAMP);
ТипаTIMMYSTAMP
не существует, но SQLite спокойно принимает его.
В SQLite есть пять типов:NULL
,INTEGER
,REAL
,TEXT
,BLOB
. Хотите узнать нечто безумное? Аффинность типов работает при помощи сопоставления подстрок!
CREATE TABLE t(value SPONGEBLOB) --- Это тип BLOB!
Поэтому случается и такое:
Имейте в виду, что объявленный тип «FLOATING POINT» придаст аффинность INTEGER, а не REAL, потому что в конце «POINT» есть подстрока «INT».
- Это одна из моих любимых историй. SQLite пришлось сменить стандартный префикс с
sqlite_
наetilqs_
, когда пользователи начали звонить разработчикам по ночам.
- SQLite очень серьёзно относится к обратной совместимости
«Все релизы SQLite версии 3 могут читать и записывать файлы баз данных, созданные самым первым релизом SQLite 3 (версией 3.0.0), выпущенным 18 июня 2004 года. Вот это и называется «обратной совместимостью». Разработчики обещают сохранять обратную совместимость формата файлов баз данных для всех будущих релизов SQLite 3».
- Но они воспринимают обратную совместимость настолько серьёзно, что, даже если выпустили код с багом, то не будут устранять его.
- Автор SQLite Ричард Хипп (D. Richard Hipp, DRH) не нашёл ни одной подходящей ему готовой системы контроля версий, поэтому написал собственную под названием Fossil. Разумеется, Fossil основана на SQLite.
Это напомнило мне о том, как Линус написал Git.
Также DRH написал собственный генератор парсеров Lemon. - DRH написал B-дерево на основании алгоритма из книги Дональда Кнута «Искусство программирования»; при этом он писал код на борту самолёта.
- SQLite произносится как «Эс-Кью-Эл-айт» («Ess-Cue-El-ite»). Однако официального произношения не существует. На форумах по SQLite DRH оставил такое сообщение:
Я написал SQLite и думаю, название должно произноситься, как «S-Q-L-ite». Но вы вполне можете произносить его, как угодно.
:-)
▍ Источники
1. Самая развёртываемая, общественное достояние и вклад, тестирование, платная поддержка, быстрее, чем файловая система, история SQLite.
2. Я опубликовал эту статью на Twitter, и люди дали мне ссылки на дополнительные источники. Спасибо им: 1, 2, 3, 4, 5.
Telegram-канал со скидками, розыгрышами призов и новостями IT ?

Комментарии (66)
SergeiZababurin
15.01.2025 13:18Спасибо. Мне про sqlite рассказывалточень сильный разработчик в Альпари когда работал.
Прочитал статью, как в прошлое вернулся )
Format-X22
15.01.2025 13:18Для торговых ботов в связке с Rust хорошо подходит, как раз требование к надежности уровня военного корабля, много параллельных читателей-писателей не нужно, ну и меньше зависимостей - меньше точек отказа, никаких отдельных серверов или контейнеров, компактно и надежно. Все мои кейсы использования SQLite были такими.
Nn111
15.01.2025 13:18Очень удобно для десктопа. Вроде даже визуал студия данные проектов в склайт хранит.
А так хоть и в настройках есть выбор многих фреймворков например, но в реальных веб сервисах ни разу не видел склайт.
vvzvlad
15.01.2025 13:18но в реальных веб сервисах ни разу не видел склайт.
Думается мне, процентов 90 веб-сервисов используют sqlite :)
randomsimplenumber
15.01.2025 13:18Приблизительно 0%. У SQLite очень плохо с параллельной записью
vvzvlad
15.01.2025 13:18С какой параллельной, о чем вы?
randomsimplenumber
15.01.2025 13:18Ну, скажем, 2 клиента этого веб-сервиса одновременно нажали кнопку "обновить". Если клиентов больше 10 - сервис будет очень сильно тупить.
uranik
15.01.2025 13:18Так вэб сервис все параллельные записи может выстроить в последовательную очередь и быстро записать в sqlite.
randomsimplenumber
15.01.2025 13:18Ну, можно конечно изобрести свой движок поверх SQLite. недоmysql ;)
mayorovp
15.01.2025 13:18Ну, так в итоге и будет сделано, однако необходимость подобного строгого упорядочивания означает более близкий потолок производительности.
ShashkovS
15.01.2025 13:18У вас устаревшие данные.
import os import sqlite3 import time import multiprocessing import uuid def writer_process(proc_id, num_inserts, db_file): conn = sqlite3.connect(db_file) conn.execute("PRAGMA busy_timeout = 5000") conn.execute("PRAGMA synchronous = NORMAL") for _ in range(num_inserts): with conn: conn.execute("INSERT INTO test_data (val) VALUES (?)", (str(uuid.uuid4()),)) def run(num_processes, num_inserts, test_id=1): start_time = time.perf_counter() db_name = f'db{test_id}.sqlite' conn = sqlite3.connect(db_name) conn.execute("PRAGMA journal_mode = WAL") conn.execute("CREATE TABLE IF NOT EXISTS test_data (id INTEGER PRIMARY KEY, val TEXT)") conn.commit() conn.close() processes = [] for i in range(num_processes): p = multiprocessing.Process(target=writer_process, args=(i, num_inserts, db_name)) processes.append(p) print(f'Тестируем {num_processes} процессов') for p in processes: p.start() for p in processes: p.join() os.unlink(db_name) total_time = time.perf_counter() - start_time total_inserts = num_processes * num_inserts print( f"{num_processes} процессов. Общее время: {total_time:.4f} секунд. Суммарная скорость: {total_inserts / total_time:.2f} транзакций/сек") if __name__ == "__main__": num_inserts = 277200 for num_processes in range(1, 21): run(num_processes, num_inserts // num_processes)
У меня максимум на 4 одновременных процессах --- 70К транзакций в секунду.
Дальше до 20 процессов --- около 30К транзакций в секунду. И это в режиме, когда все процессы только и делают, что пишут в одную общую нагруженную таблицу.Если вы пишете асинхронный вебсервис, то там будет столько воркеров, сколько у вас физических ядер. То есть до 20 воркеров --- всё ок, это достаточно высокая нагрузка.
Не high load, конечно, но..
mysherocker
15.01.2025 13:18Автор SQLite Ричард Хипп (D. Richard Hipp, DRH) не нашёл ни одной подходящей ему готовой системы контроля версий, поэтому написал собственную под названием Fossil. Разумеется, Fossil основана на SQLite.
Это напомнило мне о том, как Линус написал Git.
Это неудивительно, ведь Fossil вышел в 2006 году, не так уж сильно позже Git, разработка которого только началась в апреле 2025. Вероятно, разработка Fossil началась до публикации Git. А даже если и после, то тогда Git точно не был распространённой системой контроля версий.
Помимо этого, пособ хранения изменений в git до сих пор вызывает споры. так что я допускаю, что если бы даже разработчики sqlite знали тогда о git, то сознательно решили бы пойти иным путём
Dynasaur
Не понятно зачем для каждого эсминца писать своё ПО. Ещё и свою СУБД. Однопользовательскую.
Volodichev
USS Oscar Austin, это эсминец типа Арли Бёрк. Первый эсминец из серии IIa. Логично, что в новой серии кораблей обновили корабельные системы, по сравнению с предыдущими сериями.
А когда на ПСИ новая система не заработала как надо, то решили разработать костыль. Костыль вышел удачным.
a1excoder
ну да, гораздо лучше написать десяток тысяч опен сорс модулей в проект мин. обороны.. поколение pip install