【问题标题】:Slow Mysql Query with 3 left join带有 3 个左连接的慢速 Mysql 查询
【发布时间】:2014-02-15 20:14:57
【问题描述】:

我们有一个电子商店,在这个电子商店中,类别和产品之间有许多复杂的链接。

我正在使用分类表将 Products-Categories 和 Products-Products 之间的关系存储为子产品。

产品可能属于多个类别。 产品可能是其他产品的子产品。 (可能不止一个) 产品可能是其他产品的一个模块(可能不止一个)

查询的别名: 公关产品 ct-类别 sp-子产品 md-模块

Select pr.*,ifnull(sp.destination_id,0) as `top_id`,
    ifnull(ct.destination_id,0) as `category_id` 
from Products as pr
Left join Taxonomy as ct
  on (ct.source_id=pr.id and ct.source='Products' and ct.destination='Categories')
Left join Taxonomy as sp 
  on (sp.source_id=pr.id and sp.source='Products' and sp.destination='Products' and sp.type='TOPID')
Left join Modules as md
  on(pr.id = md.product_id)
where pr.deleted=false
  and ct.destination_id='47'
  and sp.destination_id is null
  and md.product_id is null
order by pr.order,pr.sub_order

有了这个查询;我正在尝试获取 Category_id=47 下的所有产品,而不是任何产品的模块,而不是任何产品的子产品。

此查询需要 23 秒。 产品中有 7.820 条记录,模块中有 3.200 条记录,分类中有 19.000 条记录

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    我本来想说 MySQL 每次查询只能使用一个索引,但现在情况似乎不再如此了。我也在另一个答案中遇到了这个: http://dev.mysql.com/doc/mysql/en/index-merge-optimization.html

    但是,这可能对您没有帮助。

    过去,当我遇到 MySQL 无法优化的查询时,我已经决定使用后台作业在另一个表中预先计算答案。

    您正在尝试执行的操作看起来非常适合 neo4j 之类的图形数据库。

    【讨论】:

      【解决方案2】:

      众所周知,MySQL 的优化器在自动将外部联接更改为内部联接方面很糟糕,它先执行外部联接,然后开始过滤数据。

      在您的情况下,Products 和 Taxonomy 之间的联接可以重写为内部联接(ct.destination_id='47' 上有 WHERE 条件)。

      尝试这是否会改变执行计划并提高性能。

      【讨论】:

        猜你喜欢
        • 2015-02-22
        • 2019-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-06
        • 2019-08-24
        • 1970-01-01
        相关资源
        最近更新 更多