将标签存储在数据库中的最佳实践?

Joh*_*ans 23 mysql tags optimization performance structure

我开发了一个使用标签(关键词)的网站,以便对照片进行分类.现在,我在MySQL数据库中拥有的是一个具有以下结构的表:

image_id (int)
tag      (varchar(32))
Run Code Online (Sandbox Code Playgroud)

每当有人标记图像(如果标记有效并且有足够的投票),它就会被添加到数据库中.我认为这不是最佳的做事方式,因为现在我有5000个带标签的图像,标签表有超过40000个条目.我担心这会开始影响性能(如果它还没有影响它).

我认为这个其他结构认为获取与特定图像相关联的标签会更快,但是当我想要获取所有标签或者最常用的标签时,它看起来很糟糕:

image_id (int)
tags     (text) //comma delimited list of tags for the image
Run Code Online (Sandbox Code Playgroud)

有没有一种正确的方法可以做到这一点,或者两种方式都或多或少相同?思考?

OMG*_*ies 11

使用多对多表将TAG记录链接到IMAGE记录:

图片

DROP TABLE IF EXISTS `example`.`image`;
CREATE TABLE  `example`.`image` (
  `image_id` int(10) unsigned NOT NULL auto_increment,
  PRIMARY KEY  (`image_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)

标签

DROP TABLE IF EXISTS `example`.`tag`;
CREATE TABLE  `example`.`tag` (
 `tag_id` int(10) unsigned NOT NULL auto_increment,
 `description` varchar(45) NOT NULL default '',
 PRIMARY KEY  (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)

IMAGE_TAG_MAP

DROP TABLE IF EXISTS `example`.`image_tag_map`;
CREATE TABLE  `example`.`image_tag_map` (
 `image_id` int(10) unsigned NOT NULL default '0',
 `tag_id` int(10) unsigned NOT NULL default '0',
 PRIMARY KEY  (`image_id`,`tag_id`),
 KEY `tag_fk` (`tag_id`),
 CONSTRAINT `image_fk` FOREIGN KEY (`image_id`) REFERENCES `image` (`image_id`),
 CONSTRAINT `tag_fk` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)

  • 逗号分隔列表是非规范化数据 - "IMAGE_TAG_MAP"是相同信息的示例,但已标准化. (2认同)

Dal*_*kas 5

在多标签搜索查询中,您必须点击所请求的每个标签。因此,图像标签集I必须是请求标签集U的超集。

I >= U
Run Code Online (Sandbox Code Playgroud)

在 SQL 中实现这种复杂的比较是一个挑战,因为每个图像都必须单独进行限定。鉴于每个图像的标签是唯一设置的:

SELECT i.* FROM images AS i WHERE {n} = (
  SELECT COUNT(*) 
  FROM image_tags AS t 
  WHERE t.image_id = i.image_id
    AND t.tag IN ({tag1}, {tag2}, ... {tagn})
)
Run Code Online (Sandbox Code Playgroud)

架构:

CREATE TABLE images (
  image_id varchar NOT NULL,
  PRIMARY KEY (image_id)
)

CREATE TABLE image_tags (
  image_id varchar NOT NULL,
  tag varchar NOT NULL,
  PRIMARY KEY (image_id, tag)
)
Run Code Online (Sandbox Code Playgroud)


Mat*_*son 4

您可以创建一个tags表,该表只是一个idand ,并且对具有和 的表具有tag唯一约束。仅当标签尚不存在时才将其插入表中。tagphoto_tagstag_idphoto_idtags

然后,在执行诸如有多少张照片被标记为某个标签之类的查询时,您将通过 pk 而不是 varchar 文本比较进行查询。