【问题标题】:MySQL select with multiple many to many joins causing very slow query具有多个多对多连接的 MySQL 选择导致查询非常慢
【发布时间】:2014-11-18 12:22:58
【问题描述】:

使用如下表结构:

项目(约 20,000 条记录)

  • item_id

属性(约 30 条记录)

  • property_id

Item_properties(约 40,000 条记录)

  • 身份证
  • property_id
  • item_id

用户可以选择通过items 表本身中的多个字段来过滤项目,也可以选择项目必须具有的任意数量的properties。搜索需要选择具有 all 属性的项目,而不仅仅是其中一个。我目前使用的格式

SELECT item.field...
FROM items
INNER JOIN item_properties AS ip1 ON ip1.item_id=item.item_id and ip1.property_id=3
INNER JOIN item_properties AS ip2 ON ip2.item_id=item.item_id and ip2.property_id=4
INNER JOIN item_properties AS ip3 ON ip3.item_id=item.item_id and ip3.property_id=5
INNER JOIN item_properties AS ip4 ON ip4.item_id=item.item_id and ip4.property_id=6
etc...
WHERE item.something_else='words'
GROUP BY item_id

我也尝试过,作为一种纯粹通过 WHERE 而不是 JOIN 指定搜索的方式

SELECT item.field...
FROM items
WHERE item.something_else='words'
and item_id IN (select item_id from item_properties where property_id=3)
and item_id IN (select item_id from item_properties where property_id=4)
and item_id IN (select item_id from item_properties where property_id=5)
and item_id IN (select item_id from item_properties where property_id=6)
etc...

但是,如果有的话,这种方法似乎需要更长的时间来查询集合。选择了大约 4 个属性,查询时间大约是 4-5 秒,而且查询往往会被终止或完全关闭 MySQL 服务器。

据我所知,所有 _id 字段都在每个表上都有索引,它们也是各自表的主键。

有没有办法改进查询,或者我可能需要限制可以查询的选项数量?

【问题讨论】:

  • INNER JOIN item_properties AS ip1 ON ip1.item_id=item.item_id 和 ip1.property_id IN(3,4,5,6)
  • 谢谢;用于创建 OR 样式搜索,其中项目必须具有至少一个属性。我实际上希望该项目具有 ALL 选择的属性。

标签: mysql join many-to-many mysql-slow-query-log


【解决方案1】:

如果您想要所有 property_id,请使用聚合后过滤

SELECT item.field
FROM items
INNER JOIN item_properties AS ip1 ON ip1.item_id=item.item_id and  
and ip1.property_id IN(3,4,5,6)
WHERE item.something_else='words'
GROUP BY item.field
HAVING COUNT(DISTINCT property_id )=4

4是property_id IN(3,4,5,6)的个数

【讨论】:

  • 这似乎运作良好;使用HAVING 不会显着改变查询时间,它比向多连接或子查询方法添加更多索引要快。
【解决方案2】:

我认为您只需要在item_properties 上建立索引:

create index idx_item_properties_2 on item_properties(item_id, property_id)

【讨论】:

  • 在功能上与该表上已被索引的 item_id 和 property_id 是否不同?
  • 我已经创建了它,它确实加快了上面使用的多重连接方法。最大可能的查询仍然需要 4.5 秒,但比崩溃 MySQL 要好得多。我认为为了提高实际查询的效率,我可能会选择使用HAVING 的答案,但这很有帮助。
  • @M1ke 。 . .为什么你有group by item_id?如果您没有重复的属性,那么这应该是不必要的(您可能会发现删除它会给您带来另一个性能提升)。
  • @M1ke 。 . .复合索引不同于列上的两个独立索引。
  • 难道不需要该组来防止每个项目/属性组合出现一行吗? IE。如果使用连接,则项目所具有的每个属性都会显示相同的项目信息?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-30
  • 2019-12-28
  • 2017-03-18
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 1970-01-01
相关资源
最近更新 更多