【问题标题】:Multiple left joins and performance多个左连接和性能
【发布时间】:2012-02-22 16:16:58
【问题描述】:

我有以下表格:

产品 - 4500 条记录

字段:id、sku、名称、别名、价格、special_price、数量、desc、照片、manufacturer_id、model_id、hits、publishing

products_attribute_rel - 35000 条记录

字段:id、product_id、attribute_id、attribute_val_id

attribute_values - 243 条记录

字段:id、attr_id、值、排序

制造商 - 29 条记录

字段:id、title、publishing

模型 - 946 条记录

字段:id、manufacturer_id、title、publishing

所以我通过一个查询从这些表中获取数据:

SELECT jp.*,
       jm.id AS jm_id,
       jm.title AS jm_title,
       jmo.id AS jmo_id,
       jmo.title AS jmo_title
FROM `products` AS jp 
LEFT JOIN `products_attribute_rel` AS jpar ON jpar.product_id = jp.id
LEFT JOIN `attribute_values` AS jav ON jav.attr_id = jpar.attribute_val_id
LEFT JOIN `manufacturers` AS jm ON jm.id = jp.manufacturer_id
LEFT JOIN `models` AS jmo ON jmo.id = jp.model_id 
GROUP BY jp.id HAVING COUNT(DISTINCT jpar.attribute_val_id) >= 0 

这个查询慢得要命。 mysql需要数百秒来处理它。 那么如何改进这个查询呢?对于小数据块,它可以工作 非常好。但我想一切都毁了products_attribute_rel 桌子, 有 35000 条记录。

您的帮助将不胜感激。

已编辑

EXPLAINSELECT 查询的结果:

【问题讨论】:

  • 您可能需要创建非集群覆盖索引。
  • 你有没有使用b-tree之类的索引方法?
  • EXPLAIN 放在SELECT 前面,然后向我们展示结果。这可能有助于我们找出瓶颈是什么。
  • 我已经编辑了我的帖子。所以现在您可以在屏幕截图中看到 EXPLAIN 查询结果。
  • 灾难不是 35K 行的(小)表。这是您在 5 个表中的 3 个上没有索引(除了 PRIMARY KEYs)。在用于连接的每一列上添加一个索引。

标签: mysql


【解决方案1】:

问题是 MySQL 对 3 个表使用连接类型 ALL。这意味着 MySQL 执行 3 次全表扫描,将所有可能性放在一起,然后再将那些与 ON 语句不匹配的可能性排序。要获得更快的连接类型(例如 eq_ref),您必须在 ON 语句中使用的列上放置一个索引。

请注意,不建议在每个可能的列上放置索引。许多索引确实加快了SELECT 语句的速度,但是它也会产生开销,因为必须存储和管理索引。这意味着像UPDATEDELETE 这样的操作查询要慢得多。我看到查询在半小时内只删除了 1000 条记录。这是一种权衡,您必须决定哪些事情发生得更频繁,哪些事情更重要。

要获取有关 MySQL 连接类型的更多信息,请查看this
更多关于索引here

【讨论】:

  • 谢谢迈克。我放置了索引,现在一切正常。
【解决方案2】:

表格数据并不庞大,需要数百秒。表架构有问题。请进行适当的索引。那肯定会加快速度。

【讨论】:

    【解决方案3】:
    select distinct
    jm.id AS jm_id,
    jm.title AS jm_title,
    jmo.id AS jmo_id,
    jmo.title AS jmo_title
    from products jp, 
    products_attribute_rel jpar,
    attribute_values jav,
    manufacturers jm
    models jmo
    where jpar.product_id = jp.id
    and jav.attr_id = jpar.attribute_val_id
    and jm.id = jp.manufacturer_id
    and jmo.id = jp.model_id
    

    如果您想选择所有数据,您可以这样做。希望它有效。

    【讨论】:

      猜你喜欢
      • 2013-05-18
      • 2020-12-02
      • 2021-08-02
      • 2015-04-04
      • 2019-09-03
      • 2023-03-16
      • 2015-06-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多