使用union和left join的mysql查询速度较慢

使用union和left join的mysql查询速度较慢,mysql,join,union,Mysql,Join,Union,上面的查询非常慢,1分钟。如果我只做联合部分,它会很快。或者只使用products表,而不使用union表 我在这里干什么? 产品有变体,所以我将产品和产品变体结合起来,以获得一个包含产品代码和示例参考编号的项目列表。 然后,我加入到库存列表表,其中包含来自另一个系统的大约50000行产品代码和示例参考代码,这样我就可以得到一个没有匹配ProductCode或SampleRefNum的记录列表 ------编辑 我在所有表的ProductID、ProductCode和sampleefnum上都有

上面的查询非常慢,1分钟。如果我只做联合部分,它会很快。或者只使用products表,而不使用union表

我在这里干什么? 产品有变体,所以我将产品和产品变体结合起来,以获得一个包含产品代码和示例参考编号的项目列表。 然后,我加入到库存列表表,其中包含来自另一个系统的大约50000行产品代码和示例参考代码,这样我就可以得到一个没有匹配ProductCode或SampleRefNum的记录列表

------编辑

我在所有表的ProductID、ProductCode和sampleefnum上都有索引

-这很快---

SELECT p.*
FROM (
    SELECT ProductID,ProductName,ProductCode,SampleRefNum 
    FROM products
    WHERE hidden = 'N'
    UNION ALL
    SELECT product_variants.ProductID,products.ProductName,product_variants.ProductCode,product_variants.SampleRefNum
    FROM product_variants
    JOIN products 
    ON product_variants.ProductID = products.ProductID
    ) AS p

LEFT JOIN stock_list AS s
ON p.ProductCode = s.ProductCode OR p.SampleRefNum = s.SampleRefNum
WHERE s.ProductCode IS NULL AND p.ProductCode IS NOT NULL AND p.ProductCode <> "" OR s.SampleRefNum IS NULL AND p.SampleRefNum IS NOT NULL AND p.SampleRefNum <> "" 
--这需要10秒

 SELECT p.ProductID,p.ProductName,p.ProductCode,p.SampleRefNum FROM products AS p
LEFT JOIN stock_list AS s
ON p.ProductCode = s.ProductCode OR p.SampleRefNum = s.SampleRefNum
WHERE p.Hidden = 'N' AND (s.ProductCode IS NULL AND p.ProductCode IS NOT NULL AND p.ProductCode <> "" OR s.SampleRefNum IS NULL AND p.SampleRefNum IS NOT NULL AND p.SampleRefNum <> "" )
AND (p.ProductID NOT IN(SELECT ProductID FROM product_variants) )
一般来说,加入一个或条件将是缓慢的。我建议您使用exists或更简单的左连接重新表述查询。但是,您可以尝试使用两个左连接,看看这是否符合您的要求:

SELECT p.*
FROM (
    SELECT ProductID,ProductName,ProductCode,SampleRefNum 
    FROM products
    WHERE hidden = 'N'

    ) AS p

LEFT JOIN stock_list AS s
ON p.ProductCode = s.ProductCode OR p.SampleRefNum = s.SampleRefNum
WHERE s.ProductCode IS NULL AND p.ProductCode IS NOT NULL AND p.ProductCode <> "" OR s.SampleRefNum IS NULL AND p.SampleRefNum IS NOT NULL AND p.SampleRefNum <> "" 

您将从from子句中删除连接,这需要相同的索引。

您可以发布解释计划吗?你检查过索引吗?如果你愿意,考虑下面这个简单的两步过程:1。如果您还没有这样做,请提供适当的DDL和/或SQLFIDLE,以便我们可以更轻松地复制问题。2.如果尚未这样做,请提供与步骤1中提供的信息相对应的所需结果集。
SELECT p.*
FROM (SELECT ProductID, ProductName, ProductCode, SampleRefNum 
      FROM products p
      WHERE hidden = 'N'
      UNION ALL
      SELECT pv.ProductID, p.ProductName, pv.ProductCode, pv.SampleRefNum
      FROM product_variants pv JOIN
           products p
           ON pv.ProductID = p.ProductID
     ) p LEFT JOIN
     stock_list s1
     ON p.ProductCode = s1.ProductCode LEFT JOIN
     stock_list s2
     ON p.SampleRefNum = s2.SampleRefNum
WHERE (s1.ProductCode IS NULL AND p.ProductCode IS NOT NULL AND p.ProductCode <> '') OR
      (s2.SampleRefNum IS NULL AND p.SampleRefNum IS NOT NULL AND p.SampleRefNum <> '')
WHERE (NOT EXISTS (select 1
                   from stock_list s1
                   where p.ProductCode = s1.ProductCode
                  ) and
       p.ProductCode is not null and p.ProductCode <> ''
      ) AND
      (NOT EXISTS (select 1
                   from stock_list s2
                   where p.SampleRefNum = s1.SampleRefNum
                  ) and
       p.SampleRefNum is not null and p.SampleRefNum <> ''
      )