Секционное хранение статьи в базе данных

12
O
На сайте с 29.05.2008
Offline
195
1429

Здравствуйте.

Создаю блог и столкнулся с вопросом хранения публикаций.

Публикации разделены на секции, фигуры (картинки с подписями, видео, аудио), списки, ... И каждая из секций имеет заголовок, а возле этого заголовка нужно выводить статический системный код (добавление секции в закладки).

Я выбирал между 3 вариантами: хранение html кода прямо в строке записи таблицы article - разбор по regex и разбор по DOMDocument; хранение статьи в отдельных таблицах: section FK article, paragraph FK section, figure FK section.

Я выбрал последний вариант.

Соответственно, я могу как угодно оформлять секции (на данный момент выбрал тег section), что угодно добавлять возле заголовков, добавлять кнопку "читать далее" к последнему абзацу и так далее. То-есть, в базе содержится только важная читабельная информация, а все форматирование возлагается на сторону PHP.

1. Насколько ущербная в плане производительности выборка по данной архитектуре?

2. Что лучше: выборка сначала секций к статье, потом абзацев и фигур к секции отдельными запросами или все одним запросом с последующим FULL OUTER JOIN и группировкой по позиции в статье?

iqmaker
На сайте с 17.04.2012
Offline
309
#1

я так понимаю структура таблиц будет такая: таблица статья, таблица секции, таблица связей вроде

Article

[id, title]

Section

[id, title, body]

ArticleSection

[article_id, section_id]

Если да, то проблем с производительностью быть не должно все в рамках привычного использования реляционных бд.

---------- Добавлено 22.10.2014 в 02:54 ----------

Вы уверены, что секции надо делить на три разные таблицы? Вероятно там сильно много общего наверняка можно обойтись одной. Тогда и проблем с выборкой из трех таблиц не будет, а архитектура предполагающая FULL OUTER JOIN имхо заслуживает того, чтобы ее пересмотрели.

O
На сайте с 29.05.2008
Offline
195
#2

iqmaker, почти:

Таблица article (id, uri (адрес статьи), title (название статьи = h1), date-modified, owner (автор)).

- Таблица section (id, article (внешний ключ к article.id) title (название секции = h2), position (позиция объекта относительно начала статьи)).

-- Таблица paragraph, figure, ... child (объекты секции) - поля индивидуальные, например, для figure это figcaption и ссылка на объект, но у всех есть внешний ключ к section.id и position.

Просто у меня фрустрация после работы с WordPress, DLE. Кругом для форматирования текста используют регулярные выражения, а статью сохраняют в обычном HTML коде.

Но снова таки, HTML это служебные данные и должно создавать множество проблем, начиная от увеличения потребления ОЗУ (я думаю), заканчивая фиктивными результатами поиска скажем по LIKE '%<p>%' (найдет все абзацы, вместо того, чтобы найти все статьи в которых рассказывается по значении тега p).

О regex говорить не стоит, он просто не предназначен для работы с динамическим HTML контентом. В любом случае, стабильное во всех случаях выражение будет явно менее продуктивнее DOMDocument.

---------- Добавлено 22.10.2014 в 02:09 ----------

ortegas:
Вы уверены, что секции надо делить на три разные таблицы? Вероятно там сильно много общего наверняка можно обойтись одной. Тогда и проблем с выборкой из трех таблиц не будет, а архитектура предполагающая FULL OUTER JOIN имхо заслуживает того, чтобы ее пересмотрели.

Я в плане проектирования БД newbe. :(

Вот вам отрывок кода

<article>
<header>
<h1>Neque porro quisquam est qui dolorem</h1><time datetime="2014-09-02T00:00:00+0000">Yesterday</time>
</header>
<figure>
<img src="/image/poster.jpg" alt>
<figcaption>Suspendisse ipsum risus, ullamcorper nec ultrices id, blandit nec lorem.</figcaption>
</figure>
<section id="1">
<header>
<h2>Nullam vel convallis leo, aliquam feugiat turpis. In varius tortor mollis faucibus vestibulum.</h2><a class="button" href="#1">Mark chapther</a>
</header>
<p>Nullam vel convallis leo, aliquam feugiat turpis.</p>
</section>
</article>

В данном случае, figure относится к section, у которого нету title, а в этом случае, section опускается в форматировании.

В БД хранится только название ресурса figure, а полный адрес задает система. В случае же хранения HTML кода, мне бы опять-таки, пришлось бы изощрятся с regex.

Если INSERT я еще могу представить с помощью транзакции, то выборку из 3 таблиц трудно. Тем-более FULL OUTER в MySQL нету. Хотя это именно то, что я хочу получать в ответ.

iqmaker
На сайте с 17.04.2012
Offline
309
#3

ortegas, понять бы еще, зачем вы хотите выделять из текста по regexp его внутреннюю структуру, зачем она вам? Хочется именно выяснить какую цель приследуете. Вы делаете свою CMS? у которой разработчиком сайта и наполнителем контента будет конечный пользователь?

O
На сайте с 29.05.2008
Offline
195
#4

iqmaker, тривиальный пример, вставить в последний абзац аннотации кнопку "Читать далее". Если структуру абзацев не выделить, надо либо regex, либо DOMDocument.

Следующий пример - заголовок секции (h2). Возле него, должна выводится кнопка "Добавить в закладки". Закладка на секции должна запоминаться на стороне сервера.

Третий пример - списки. Возле каждого li, в зависимости от раздела, а именно в разделе с кулинарными рецептами, должны присутствовать checkbox, которые запоминаются на стороне сервера, чтобы пользователь вернувшись, увидел то самое состояние списка.

В случае хранения HTML кода, мне постоянно надо выполнять массу regex. А закладки и состояния списка все-равно нужно хранить привязав к пользователю, только вместо FK, там что я укажу??? Номер секции по счету? Так при редактировании статьи, мне надо будет все закладки переписать что ли?

Ну и опять-таки, стараюсь свести все к нормальному состоянию. Я все-таки новичок и лишняя формализация = не лишняя.

iqmaker
На сайте с 17.04.2012
Offline
309
#5

ortegas, ок становится немного прозрачнее, что не совсем CMS, а некоторый сайт со своей спецификой и внутренними объектами так? Объекты страницы чем отличаются друг от друга?

---------- Добавлено 22.10.2014 в 15:21 ----------

Что-то мне подсказывает, что можно обойтись структурой которую указал в первом посте, добавив в таблицу Section поле section_type ...

---------- Добавлено 22.10.2014 в 15:23 ----------

Но в целом в вашем варианте нет ничего плохого, если выборка из 3 таблиц тремя запросами это вполне себе ок, для такого варианта сайта в котором несколько типов объектов.

---------- Добавлено 22.10.2014 в 15:25 ----------

Если уже есть готовая структура базы именно этих таблиц, было бы понятнее

O
На сайте с 29.05.2008
Offline
195
#6

iqmaker, в первую очередь, это статьи. Специфика - чисто моя инициатива. Смотрите.

Статья разделена на секции для удобства чтения. Каждую секцию можно добавить в закладки с помощью кнопочки, которая отображается справа от h2 заголовка секции. При последующем открытии статьи с помеченной секцией, пользователь будет сразу же переброшен на часть, где он завершил чтении через #section-#.

В статье могут присутствовать интерактивные списки. Хороший пример - список закупок для приготовления рецепта.

  • Майонез.
  • Артишоки.
    • Касательно фигур, тут тоже хотелось бы хранить адрес на изображение отдельно. Точнее, внутренний идентификатор изображения. Почему? - Я планирую подключения CloudFire. Соответственно, если я буду хранить фигуры в HTML коде, мне придется переписывать все адреса изображения руками с относительных внутредоменных на CDN.

      ---------- Добавлено 22.10.2014 в 14:30 ----------

      iqmaker:
      Но в целом в вашем варианте нет ничего плохого, если выборка из 3 таблиц тремя запросами это вполне себе ок, для такого варианта сайта в котором несколько типов объектов.
      И еще вопрос: как в моем случае сохранять позицию объекта относительно статьи? Отдельное поле position для каждого дочериного объекта? А не плохо ли то, что эта position будет зависеть от других соседних объектов с другим типом? Например, figure.position = 1, paragraph.position = 2. Но при этом, 2 не имеет смысла без 1?

      ---------- Добавлено 22.10.2014 в 14:39 ----------

iqmaker
На сайте с 17.04.2012
Offline
309
#7
ortegas:
Статья разделена на секции для удобства чтения. Каждую секцию можно добавить в закладки с помощью кнопочки, которая отображается справа от h2 заголовка секции. При последующем открытии статьи с помеченной секцией, пользователь будет сразу же переброшен на часть, где он завершил чтении через #section-#.

Добавить в закладки по h2 некоторой статьи можно чисто javascript + cookies, ( пронумеровав их при загрузке страницы тем же javascript ) или хочется на разных устройствах помнить?

ortegas:
В статье могут присутствовать интерактивные списки. Хороший пример - список закупок для приготовления рецепта.
  • Майонез.
  • Артишоки.

В общем если правильно понял расчитываете на зарегистрированного пользователя .. ок ( если нет то тоже js мог справиться )

ortegas:
После последнего абзаца аннотации статьи, должна выводится кнопка "Читать далее". Обычно, ее добавляют с помощью regex к последнему абзацу. Но снова-таки, я считаю, что в моем случае, хранение HTML кода в базе неуместно. Одно дело, когда добавить кнопочку это единственное изменение кода, другое дело, когда нужно динамически выводить статью.

Здесь наверное да, если аннотация это вступление к некоторой статье, то возможно статья должна уметь себя показывать как аннотация.

ortegas:
Касательно фигур, тут тоже хотелось бы хранить адрес на изображение отдельно. Точнее, внутренний идентификатор изображения. Почему? - Я планирую подключения CloudFire. Соответственно, если я буду хранить фигуры в HTML коде, мне придется переписывать все адреса изображения руками с относительных внутредоменных на CDN.

Если так, то да изображение надо уметь обрабатывать без парсинга собственного сайта.

ortegas:
Хотелось бы одним-двумя запросом, с помощью JOIN. Но производительнее ли этот запрос?

Обычно join показывает результат равный или худший нежели два отдельных под запроса этого join, только тест скажет как будет в конкретном случае и какие именно данные будете доставать, но чуда вероятно не случится.

ortegas:
И еще вопрос: как в моем случае сохранять позицию объекта относительно статьи? Отдельное поле position для каждого дочериного объекта? А не плохо ли то, что эта position будет зависеть от других соседних объектов с другим типом? Например, figure.position = 1, paragraph.position = 2. Но при этом, 2 не имеет смысла без 1?

Ничего плохого нет, только уверены, что не хотите использовать таблицу связей (там и указывать позицию), ведь некоторую figure и др. объекты данной статьи можно было бы использовать в другой. Почему 2 не имеет смысла без 1? чем меньше тем выше, хоть -100 -10 0 10, какое именно число на мой взгляд не важно, вам же нужно только ранжировать.

ortegas:
Ах да, еще после каждым strong будет кнопка "Согласен". Что-то типа голосования по мере чтения статьи. Обратная связь.
strong дочерний к p. Для него тоже нужно создавать отдельную таблицу или уже можно как-то объединить с параграфом?

Наверное лучше использовать общую с параграфом таблицу, если только вы эти strong не начнете использовать в других статьях отдельных от первоначального параграфа.

---------- Добавлено 22.10.2014 в 16:15 ----------

В целом когда сделаете структуру базы покажите её здесь, думаю все станет гораздо яснее.

O
На сайте с 29.05.2008
Offline
195
#8
iqmaker:
Добавить в закладки по h2 некоторой статьи можно чисто javascript + cookies, ( пронумеровав их при загрузке страницы тем же javascript ) или хочется на разных устройствах помнить?

Cookie = лишний трафик, JS - замедляет сайт на стороне клиента. У меня приоритет именно на клиента, а как там оно работает уже моя задача.

iqmaker:
В общем если правильно понял расчитываете на зарегистрированного пользователя .. ок ( если нет то тоже js мог справиться )

Рассчитываю прежде всего на сессии. Это единственный ключ, который записывается в Cookie сроком на 1 год. Но снова-таки, пользователь к сессии может быть определен.

iqmaker:
ведь некоторую figure и др. объекты данной статьи можно было бы использовать в другой

Фигура в моем понимание это прежде всего figcaption. Фактически, это параграф с ресурсом. А один и тот же параграф вряд ли я буду вставлять в разные статьи.

iqmaker
На сайте с 17.04.2012
Offline
309
#9
ortegas:
Cookie = лишний трафик, JS - замедляет сайт на стороне клиента.

Не хочется спорить но cookie это максимум 4кб :)), js замедлит если делать анимации и пр. лабудень, для $(el).attr( 'id', 'any' ), вы ничего не заметите, но такими мыслями серьезно себя ограничиваете в функционале.

ortegas:
Фигура в моем понимание это прежде всего figcaption. Фактически, это параграф с ресурсом. А один и тот же параграф вряд ли я буду вставлять в разные статьи.

Вы там выше написали о том, что это может быть картинка, видео, аудио, поэтому почему нет, ведь все эти объекты могут использоваться в нескольких статьях, но вам виднее как именно будет в вашем случае

O
На сайте с 29.05.2008
Offline
195
#10
iqmaker:
js замедлит если делать анимации и пр. лабудень, для $(el).attr( 'id', 'any' )

Или мобильный телефон с Opera Mini...

iqmaker:
Вы там выше написали о том, что это может быть картинка, видео, аудио, поэтому почему нет, ведь все эти объекты могут использоваться в нескольких статьях, но вам виднее как именно будет в вашем случае

Я же не утверждаю, я же спрашиваю. Сам ничего не решил. Наверное, лучше хранить figcaption и p в одной таблице paragraph с полем resource, который уже будет FK на таблицу resource. Поле resource NULL - оформляем, как параграф, не ноль, запрашиваем ресурс и оформляем, как figure.

Так лучше?

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий