将"Toxi"方式规范化是否真的值得?(3NF)

med*_*iev 5 mysql sql optimization normalization

我正处于数据库设计的早期阶段,所以还没有最终结果,我正在使用"TOXI"3表设计作为我的线程,它有可选标签,但我不禁觉得加入是不是真的有必要,也许我需要依靠我的posts表中的一个简单的标签列,我可以在其中存储类似的varchar <tag>, <secondTag>.

所以回顾一下:

  • 是否值得在2个标签表上额外左连接的麻烦,而不是在我的posts表中只有一个标签列.
  • 有没有办法可以优化我的查询?

架构

CREATE TABLE `posts` (
    `post_id` INT UNSIGNED PRIMARY AUTO_INCREMENT,
    `post_name` VARCHAR(255)
) Engine=InnoDB;

CREATE TABLE `post_tags` (
    `tag_id` INT UNSIGNED PRIMARY AUTO_INCREMENT,
    `tag_name` VARCHAR(255)
) Engine=InnoDB;

CREATE TABLE `post_tags_map` (
    `map_id` INT PRIMARY AUTO_INCREMENT,
    `post_id` INT NOT NULL,
    `tags_id` INT NOT NULL,
    FOREIGN KEY `post_id` REFERENCES `posts` (`post_id`),
    FOREIGN KEY `post_id` REFERENCES `post_tags` (`tag_id`)
) Engine=InnoDB;
Run Code Online (Sandbox Code Playgroud)

样本数据

INSERT INTO `posts` (`post_id`, `post_name`)
  VALUES
(1, 'test');

INSERT INTO `post_tags` (`tag_id`, `tag_name`)
  VALUES
(1, 'mma'),
(2, 'ufc');

INSERT INTO `posts_tags_map` (`map_id`, `post_id`, `tags_id`)
  VALUES
(1, 1, 1),
(2, 1, 2);
Run Code Online (Sandbox Code Playgroud)

当前查询

SELECT 
    posts.*,
    GROUP_CONCAT( post_tags.tag_name order by post_tags.tag_name ) AS tags

  FROM posts
    LEFT JOIN posts_tags_map
      ON posts_tags_map.post_id = posts.post_id
    LEFT JOIN post_tags
      ON posts_tags_map.tags_id = posts_tags.tag_id

  WHERE posts.post_id = 1
  GROUP BY post_id
Run Code Online (Sandbox Code Playgroud)

结果

如果有标签:

post_id     post_name        tags
1             test           mma, ufc

Qua*_*noi 6

将所有标记放在不同的记录中(标准化)意味着您可以在需要时更轻松地重命名标记并跟踪标记名称历史记录.

SO例如,SQL Server至少重命名相关标签三次(mssql- > sqlserver- > sql-server).

将所有标记放在一个记录中(非规范化)意味着您可以使用索引为此列FULLTEXT编制索引,并一次搜索包含两个或多个标记的帖子:

SELECT  *
FROM    posts
WHERE   MATCH(tags) AGAINST('+mma +ufc')
Run Code Online (Sandbox Code Playgroud)

这也是可能的,但标准化设计效率较低.

(不要忘记调整字符的@ft_min_word_len索引标记3或更少以使其工作)

您可以组合两种设计:存储地图表和非规范化列.但这需要更多的维护.

您还可以将规范化设计存储在数据库中,并使用您提供的查询将标记提供给SphinxLucene.

这样,您可以使用MySQL全文标记搜索进行历史挖掘Sphinx,并且不需要额外的维护.