Я разрабатываю CMS, которая имеет некоторые функции контроля версий.Он основан на базе данных MySQL.
Идея состоит в том, чтобы показать посетителям публичного сайта «определенную ревизию» данных, а пользователям backoffice - предварительный просмотр «последней ревизии».Публикация чего-либо просто означает установку «определенной ревизии» равной самой последней (и, возможно, удаление данных старых ревизий).
Я читал некоторые вопросы и ответы по теме о SO, большинство из них предполагают, что держать «старые» и «новые» строки в одной и той же таблице плохо.Но, поскольку мне нужно объединить таблицы, все они «версионные», разделение старых и новых в разных таблицах также не является идеальным (как приложение должно знать, является ли «содержимое» из одной ревизии старым или новым, и, следовательно, бытьнайти в таблице "_history" или нет?).
Поэтому я решил использовать только одну таблицу для каждого «типа контента».
Конструкция, которую я использовал: каждая таблица содержит столбец «revision INT NOT NULL» (часть первичного ключа вместе со столбцом ID).
Изменение чего-либо означает вставку новой строки с измененными значениями, увеличенной редакцией, но с тем же идентификатором.
Вставка чего-либо означает вставку новой строки с увеличенным идентификатором и увеличенной редакцией.
Удаление чего-либо означает вставку пустой строки с тем же идентификатором, инкрементной ревизией и флагом «thumbstone», установленным в значение «true».
Пример: есть страницы, и есть «представления» («представление не вСмысл MVC, представление в определенном для приложения значении). «Представления» имеют версии. Одна страница имеет много представлений. Это (часть) «Представлений».
CREATE TABLE `_views` (
`_id` int(11) NOT NULL,
`_rev` int(11) NOT NULL,
`_ts` BIT(1) DEFAULT b'0',
`page` int(11) NOT NULL,
`order` int(11) NOT NULL,
PRIMARY KEY (`_id`,`_rev`)
)
Мне нужно выбрать все представления, которыестраница содержит, вплоть до «определенной ревизии», в порядке, указанном «order».
Этот запрос работает:
SELECT * FROM (
SELECT *
FROM `_views`
WHERE `page` = :page
AND `_rev` <= :revision
ORDER BY `_rev` DESC
) AS `all`
GROUP BY `_id`
HAVING `_ts` = 0
ORDER BY `order`
подзапрос выбирает все просмотры страницы, которые быликак только «опубликовано» (ревизия меньше или равна «опубликованной» ревизии). Внешний запрос группирует их в их последнюю ревизию, удаляет группы, у которых есть thumbstone и orders их по конкретным критериям приложения.
Поскольку для CMS масштабируемость и производительность имеют решающее значение, разве нет лучшего, более элегантного способа, чем подзапросы?
... или я должен просто сосредоточиться на кэшировании?