繁体   English   中英

使用group_concat标记查询

[英]Tagging query with group_concat

使用数据库模式来标记此问题的已接受答案是否可以使用可处理大量数据的group_concat进行查询? 我需要为所有标记为标记x的项目获取带有标签的项目。 使用具有约.5百万个标签的group_concat的查询在> 15秒时非常慢。 没有group_concat( 没有标签的项目)它是~0.05秒。

作为一个附带问题,SO如何解决这个问题?

这可能是一个糟糕的索引策略的情况。 调整您链接的问题的接受答案中显示的架构:

CREATE Table Items (
  Item_ID    SERIAL,
  Item_Title VARCHAR(255),
  Content    TEXT
) ENGINE=InnoDB;

CREATE TABLE Tags (
  Tag_ID     SERIAL,
  Tag_Title  VARCHAR(255)
) ENGINE=InnoDB;

CREATE TABLE Items_Tags (
  Item_ID    BIGINT UNSIGNED REFERENCES Items (Item_ID),
  Tag_ID     BIGINT UNSIGNED REFERENCES Tags  ( Tag_ID),
  PRIMARY KEY (Item_ID, Tag_ID)
) ENGINE=InnoDB;

注意:

  • MySQL的SERIAL数据类型是BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE的别名,因此被索引;

  • Items_Tags定义外键约束会在外键列上创建索引。

我建议在规范化数据和非规范化数据之间进行混合。
因此,使用eggyal提供的规范化结构,我将执行以下非规范化结构:

CREATE TABLE Items_Tags_Denormalized (
  Item_ID    BIGINT UNSIGNED REFERENCES Items (Item_ID),
  Tags     BLOB,
  PRIMARY KEY (Item_ID)
) ENGINE=InnoDB;

在列Tags您将拥有相应Item_ID所有标签( Tag_Title )。
现在你有两种方法来实现这个目标:

  • 创建一个定期运行的cron,它将构建此表Items_Tags_Denormalized使用GROUP_CONCAT或任何适合你的东西(优点:当你在Items_Tags表中插入或删除时不会产生额外的负载;缺点:非规范化表并不总是最新的(取决于关于你多久运行一次cron))

  • 在插入和删除时为Items_Tags表创建触发器以保持最新的Items_Tags_Denormalized表(优点:非规范化表将始终是最新的;缺点:在Items_Tags表中插入或删除时的额外负载)

考虑到优点和缺点,选择最适合您需求的解决方案。

因此,最后您将拥有Items_Tags_Denormalized表,您只能在不执行其他操作的情况下阅读该表。

为什么要使用group_concat呢? 对于给定的标签x,您说选择项目列表很快。 对于给定的项目列表,获取所有标签也应该很快。 并且通常没有某种限制,我的意思是普通网站不会在一个页面上显示100000个条目。

我会建议:

drop temporary table if exists lookup_item;

create temporary table lookup_item (item_id serial, primary key(item_id));

insert into lookup_item select i.id as item_id 
from items i 
where exists (select * from items_tags where item_id = i.id and tag_id = <tag_id>)
and <other conditions or limits>;

select * from lookup_item
inner join items_tags it on it.item_id = i.id
inner join tags t on t.id = it.tag_id
order by i.<priority>, t.<priority>

优先级可以针对项目进行最后修改,并对标签具有某种重要性。

然后你用它的标签得到每个项目。 代码中唯一的工作是查看结果行何时具有下一个项目。

如果我理解正确的话, GROUP_CONCAT并不是你唯一要删除的东西,它使得查询更快,没有标签。 GROUP_CONCAT您选择了Tags.Tag_Title并强制访问Tags表。

您可以尝试使用Items_Tags.Tag_ID运行GROUP_CONCAT来测试我的理论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM