2016-08-02 11 views
0

Я моделирую данные для своей сети, которую я создаю. Я использую базу данных Postgresql.Моделирование сообщений и флагов в SQL

В приложении есть сообщения, такие как сообщения SO, а также флаги для сообщений в виде флагов или меток Github, независимо от правильного термина для него. У столбца может быть только один флаг за раз. Есть много должностей, когда-либо увеличивающихся, но четыре или пять флагов, и они не будут увеличиваться.

Первый подход, нормализованный; Я смоделировал эту часть своих данных тремя таблицами; два для соответствующих объектов сообщений и флагов и один для отношения как post_flag. Никакой ссылки в любой из таблиц сущности, упомянутых в другой таблице сущностей для отношений. Все отношения записываются в таблицу отношений post_flag, и это только пара id для идентификаторов сообщения и флага.

Структура таблицы в этом случае будет:

CREATE TABLE posts 
(
    id bigserial PRIMARY KEY, 
    created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    title character varying(100), 
    text text, 
    score integer DEFAULT 0, 
    author_id integer NOT NULL REFERENCES users (id), 
    product_id integer NOT NULL REFERENCES products (id), 
); 

CREATE TABLE flags 
(
    id bigserial PRIMARY KEY, 
    created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    flag character varying(30) NOT NULL -- planned, in progress, fixed 
); 

CREATE TABLE post_flag 
(
    created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    post_id integer NOT NULL REFERENCES posts (id), 
    flag_id integer NOT NULL REFERENCES flags (id) 
); 

Чтобы получить сообщения, помеченные как фиксированные, я должен использовать:

-- homepage posts- fixed posts tab 
SELECT 
    p.*, 
    f.flag 
FROM posts p 

JOIN post_flag p_f 
ON p.id = p_f.post_id 
JOIN flags f 
ON p_f.flag_id = f.id 

WHERE f.flag = 'fixed' 
ORDER BY p_f.created_at DESC 

Второй подход; У меня есть две таблицы и флаги. Столбцы таблицы имеют столбец flag_id, который ссылается на флаг в таблице флагов.

CREATE TABLE posts 
    (
     id bigserial PRIMARY KEY, 
     created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
     title character varying(100), 
     text text, 
     score integer DEFAULT 0, 
     author_id integer NOT NULL REFERENCES users (id), 
     product_id integer NOT NULL REFERENCES products (id), 
     flag_id integer DEFAULT NULL REFERENCES flags (id) 
    ); 

    CREATE TABLE flags 
    (
     id bigserial PRIMARY KEY, 
     created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
     flag character varying(30) NOT NULL -- one of planned, in progress, fixed 
    ); 

Для одних и тех же данных;

-- homepage posts- fixed posts tab 
SELECT 
    p.*, 
    f.flag 
FROM posts p 

JOIN flags f 
ON p.flag_id = f.id 

WHERE f.flag = 'fixed' 
ORDER BY p.created_at DESC 

Третий подходденормализованной; У меня есть только один стол. Стол сообщений имеет столбец флага для хранения флага, назначенного сообщению.

CREATE TABLE posts 
     (
      id bigserial PRIMARY KEY, 
      created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, 
      title character varying(100), 
      text text, 
      score integer DEFAULT 0, 
      author_id integer NOT NULL REFERENCES users (id), 
      product_id integer NOT NULL REFERENCES products (id), 
      flag character varying(30) 
     ); 

Здесь я бы хотел получить только те же данные;

-- homepage posts- fixed posts tab 
SELECT 
    p.*, 
FROM posts p 

WHERE p.flag = 'fixed' 
ORDER BY p.created_at DESC 

Интересно, если первый подход является излишним с точки зрения нормализации данных в СУБД, как Postgresql? Для отношений с комментариями, которые первый подход был бы большим, и я действительно использую его. Но у меня очень мало данных о количестве, которые используются в качестве метаданных для сообщений в виде значков, флагов, тегов. Как вы видите на самом деле в самой нормальной форме, первый подход, я уже использую какой-то product_id и т. Д. Для использования одного менее JOIN, но для другой таблицы в качестве другого отношения, а не для флагов. Итак, мой подход вписывается в мой второй подход. Должен ли я использовать более денормализованный подход, третий, имея столбик и столбец флага в нем? Каков наилучший подход с точки зрения производительности, расширения и ремонтопригодности?

+0

Это может быть только я, но просмотр ваших разных структур таблиц был бы более полезным, чем просмотр запросов, которые вы используете против них, при оценке степени нормализации и его эффектов. – alzee

+2

Добавлены структуры данных. –

ответ

1

Использовать второй подход.

Первый многие-ко-многим структуры данных, и вы говорите

на пост может иметь только один флаг в то время.

Таким образом, вам необходимо будет построить бизнес-логику в интерфейсе или настроить сложные правила, чтобы проверять сообщение, не имеющее более одного флага.

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

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

Лично я бы сделал поле flag_id в таблице postsNULL, что позволило бы моделировать сообщение без флага.

Blending два подхода

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

CREATE TABLE posts 
(
    id bigserial PRIMARY KEY, 
    ... other fields 
    flag character varying(30) REFERENCES flags (flag) 
); 

CREATE TABLE flags 
(
    flag character varying(30) NOT NULL PRIMARY KEY, 
    created_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP 
); 

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

+0

Является ли ваш ответ по-прежнему одинаковым для части перед частью «смешивания двух подходов», если у меня есть post_id уникальный в таблице post_flag, поэтому обновления для флага сообщения сделаны там и сделаны только там, не вставляя новую строку для сообщения , Фактически, первый, похоже, имеет историю возможностей изменений, если у меня есть другой столбец идентификатора как ПК, и это делает его много-ко-многим. Если мне нужен только один флаг для одного сообщения, а также история может выбрать последнюю временную метку с предложением WHERE. –

+0

Если я правильно понимаю ваш комментарий, вы можете сделать 'post_id' основным ключом для обеспечения уникальности. Тогда да, обновления для флага изменили бы только таблицу 'post_flag'. Но это звучит для меня как преждевременная оптимизация производительности. У вас есть проблема с быстрым обновлением флага poset? (Я написал этот комментарий, прежде чем вы его отредактировали) – Tony

+0

Использование подхода «многие-ко-многим» даст вам историю флагов для сообщения, что может быть полезно. Тебе это надо? Если да, то дата создания строки post_flag может быть автоматически установлена, а затем использована для получения текущего флага. – Tony