【问题标题】:How do I pull both categories AND tags from a MySQL Database for an item?如何从 MySQL 数据库中提取项目的类别和标签?
【发布时间】:2012-08-24 23:59:12
【问题描述】:

我的数据库中有 5 个表。
[项目] - id、名称等...
[类别] - id、名称
[标签] - id、姓名

2 个连接表
[Items_Categories] - item_id, category_id
[Items_Tags] - item_id, tag_id

在给定 item_id = $id 的情况下,我只需要知道性能最佳的查询(必要时使用 JOINS)即可从数据库中提取 1 个或多个项目及其所有信息,包括类别和标签。

到目前为止,我有以下工作,但在 25 到 50 个查询中,速度很慢(有人有更好的吗?):

    SELECT `items`.`name`, `items`.`etc`,
group_concat(DISTINCT categories.name ORDER BY categories.name DESC SEPARATOR ", ") AS category, 
group_concat(DISTINCT tags.name ORDER BY tags.name DESC SEPARATOR ", ") AS tag, 
`items`.`id` AS id 
FROM (`items` AS items, `item_categories` AS categories, `items_to_categories` AS items_cats, `item_tags` AS tags, `items_to_tags` AS items_tags) 
JOIN `item_categories` ON `categories`.`id` = `items_cats`.`category_id` AND items_cats.item_id = $id 
JOIN `item_tags` ON `tags`.`id` = `items_tags`.`tag_id` AND items_tags.item_id = $id WHERE `items`.`id` = $id

【问题讨论】:

  • GROUP_CONCAT 首先,然后加入。使用子查询。
  • 找到性能最佳的查询绝非易事。使用 Explain 为您的查询添加前缀并运行它,并将结果放入您的问题中,我们现在所能做的就是猜测。
  • 子查询对我的查询编写来说几乎总是一个危险信号。此外,我认为有一些“简单”的技术可以让你获得一个非常高效的基础。真正困难的部分是对性能进行超级调整。但在有数百万行之前,我还没有注意到对它的真正需求(通过精心设计的查询)。 10 次中有 9 次,简单地了解如何根据您的 sql 构建查询计划将使您编写的查询效率提高许多数量级(如果您的架构很好的话)。
  • 哦,我不推荐子查询,但我也不推荐猜测。 :( 除非它是一个非常明显的缺失索引)解释是工作之一。如果它是一个明显的索引,那么解释是第二个工作,只是为了确保我和 DBMS 在同一页面上。
  • @ctrahey:我自己说得再好不过了。 :)

标签: php mysql sql codeigniter join


【解决方案1】:

问题在于,您实际上是先进行完全交叉连接(通过按照您所做的方式列出表),而不是有选择地“按顺序”连接并允许查询计划简化连接。尝试像这样加入以显式地仅加入适当的行。

SELECT 
  `items`.`name`, 
  `items`.`etc`,
  group_concat(DISTINCT `categories`.`name` ORDER BY `categories`.`name` DESC SEPARATOR ", ") AS category, 
  group_concat(DISTINCT `tags`.`name` ORDER BY `tags`.`name` DESC SEPARATOR ", ") AS tag, 
  `items`.`id` AS id 
FROM `items`, 
  LEFT JOIN `item_categories` ON `items`.`id` = `item_categories`.`item_id`
  LEFT JOIN `categories` ON `item_categories`.`category_id` = `categories`.`id`,
  LEFT JOIN `item_tags` ON `items`.`id` = `item_tags`.`item_id`
  LEFT JOIN `tags` ON `item_tags`.`tag_id` = `tags`.`id` 
WHERE `item`.`id` = $id
GROUP BY `item`.`id`

这将产生一个闪电般快速的查询,并且通过添加适当的索引很容易使其更快。然而,我的理念是,您应该首先进行快速查询,然后通过索引快速获取它;不使用索引作为第一方法。

【讨论】:

  • 谢谢,这就像一个魅力,是一个明显的改进。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-26
相关资源
最近更新 更多