SQL needed structure
- Данные на странице IMDB иерархические: фильм → режиссёр, жанры, актёры → персонажи.
- Иерархия двунаправленная: фильм→актеры и актер→фильмы.
- Реляционная БД хранит всё в плоских таблицах; при выводе строим нужную иерархию.
- Ручная сборка — утомительна, это «объектно-реляционное несоответствие».
SQL не умеет выдавать структуру
Цель: JSON вида
{"title":"Baby Driver","director":["Edgar Wright"],"writer":["Edgar Wright"],
"genres":["Action","Crime","Drama"],
"actors":[{"name":"Ansel Elgort","characters":["Baby"]}, …]}
Пошаговые запросы:
-- название
SELECT primaryTitle FROM title WHERE tconst='tt3890160';
-- режиссёры
SELECT p.primaryName
FROM title t
JOIN principal pr ON t.tconst=pr.tconst
JOIN person p ON pr.nconst=p.nconst
WHERE t.tconst='tt3890160' AND pr.category='director';
-- сценаристы
... AND pr.category='writer';
-- актёры
SELECT p.nconst, p.primaryName
FROM title t
JOIN principal pr ON t.tconst=pr.tconst
JOIN person p ON pr.nconst=p.nconst
WHERE t.tconst='tt3890160' AND pr.category='actor';
-- персонажи
SELECT pc.nconst, pc.character
FROM title t
JOIN principal pr ON t.tconst=pr.tconst
JOIN principal_character pc ON pr.nconst=pc.nconst
WHERE t.tconst='tt3890160';
Попытка объединить всё в один запрос даёт декартово произведение (режиссёры×сценаристы) и пропуск записей при отсутствии одной из ролей. Поэтому приходится делать множество отдельных запросов и собирать итоговую структуру на клиенте.
Комментарии (100)
- Обсуждение крутится вокруг «объектно-реляционного несоответствия»: SQL хорошо хранит нормализованные данные, но плохо отдаёт их иерархически.
- Многие считают, что виноват сам язык: нет встроенных вложенных отношений, агрегация в JSON делается громоздко, JOIN-ы приходится «переделывать» в коде.
- Часть участников предлагает решать задачу внутри СУБД: Postgres-функции json_agg, LATERAL-подзапросы, денормализованные VIEW и «JSON-проекции».
- Другие уверены, что проблема надумана: деревья в SQL вполне строятся (adjacency list, nested sets, closure table), просто нужно знать приёмы; ORM и NoSQL лишь откладывают боль.
- Упоминаются альтернативные пути: GraphQL-слой поверх SQL, графовые СУБД, документные хранилища (MongoDB), event-sourcing с CQRS, но каждый имеет свои trade-off.
What If OpenDocument Used SQLite?
Если бы OpenDocument использовал SQLite
Мысленный эксперимент: заменить ZIP-контейнер в формате ODP на базу SQLite.
Плюсы: компактнее, быстрее открытие/сохранение, меньше памяти, встроенная версионность.
Текущий ODP
ODP-файл — это ZIP-архив с XML-файлами (content.xml
, styles.xml
, meta.xml
, settings.xml
) и папкой Pictures
с ресурсами.
Пример: 49-слайдовая презентация — 78 файлов, 11 МБ.
Недостатки ZIP-контейнера
- Сложное инкрементальное обновление
При каждом «Сохранить» перезаписывается весь архив, что медленно и «съедает» ресурс SSD. - Медленный старт
При открытии нужно распаковать и распарсить большой XML. - Отсутствие версионности
Нет простого способа хранить историю изменений. - Избыточные данные
Каждая картинка — отдельный файл, даже если она используется многократно.
Преимущества SQLite
- Инкрементальные изменения
Обновляются только нужные строки; сохранение происходит мгновенно и безопасно (благодаря транзакциям). - Мгновенный старт
Данные уже структурированы; нет необходимости распаковывать и парсить XML. - Встроенная версионность
Таблицыslide_history
,image_versions
позволяют откатываться к любому состоянию. - Дедупликация ресурсов
Один и тот же рисунок хранится единожды; ссылки черезimage_id
. - Сжатие и индексы
SQLite сжимает данные и строит индексы по ключам (номера слайдов, идентификаторы объектов).
Схема SQLite-документа (упрощённо)
CREATE TABLE slides(
slide_id INTEGER PRIMARY KEY,
title TEXT,
xml_content BLOB,
z_order INTEGER
);
CREATE TABLE images(
image_id INTEGER PRIMARY KEY,
data BLOB,
mime_type TEXT,
sha256 BLOB UNIQUE
);
CREATE TABLE slide_images(
slide_id INTEGER REFERENCES slides,
image_id INTEGER REFERENCES images,
x REAL, y REAL, width REAL, height REAL
);
CREATE TABLE history(
change_id INTEGER PRIMARY KEY,
timestamp DATETIME,
sql BLOB
);
Итог
SQLite превращает «кучу файлов» в реляционную базу: быстрее, надёжнее, экономнее.
Это не предложение переделать ODP, а идея для следующих форматов.
Комментарии (88)
- SQLite как формат файла приложений: удобен для запросов, хранит всё в одном файле, но требует осторожности с безопасностью и сетевыми ФС.
- Ключевые советы: включать
secure_delete
, не хранить больше 2 ГиБ в BLOB, избегать работы по сети без надёжных блокировок. - Плюсы: SQL-запросы, простота API, лёгкость инспектировать и мигрировать данные (пример — Anki).
- Минусы: сложно версионировать бинарные вставки, проблемы синхронизации/коллаборации, перезапись всего файла при малом изменении.
- Альтернативы: разделение текста и бинарников, JSON + Git, XML для обмена, CRDT-структуры для офлайн-редактирования.