MySQL的性能非常差

MySQL的性能非常差,mysql,sql,database,performance,distinct,Mysql,Sql,Database,Performance,Distinct,我有一个具有多个左连接的独特Select语句,当where子句很大时,该语句的性能很差。以下是我的发言 SELECT DISTINCT u.*, ri.id as reg_id, d.id as dist_id FROM users u LEFT JOIN earned_points ep ON u.id = ep.user_id LEFT JOIN distributors d ON d.id = ep.distributor_id OR d.id

我有一个具有多个左连接的独特Select语句,当where子句很大时,该语句的性能很差。以下是我的发言

SELECT  DISTINCT u.*, ri.id as reg_id, d.id as dist_id
    FROM  users u
    LEFT JOIN  earned_points ep ON u.id = ep.user_id
    LEFT JOIN  distributors d ON d.id = ep.distributor_id
      OR  d.id = u.distributor_id
      OR  d.id = u.additional_distributor_id
    LEFT JOIN  registration_items_users riu ON u.id = riu.user_id
      AND  riu.distributor_id = d.id
      AND  riu.registration_item_id = 21
    LEFT JOIN  registration_items ri ON riu.registration_item_id = ri.id
    WHERE  d.id IN (201,281,321,631,901,971,1211,1601,1611,1621,
               1631,1641,1651,1661,1671,1681,1691,1701,1711,1721,1731,
               1741,1751,1761,1771,1781,2281,2291,2401,2781,2801,2931 );
此查询的解释如下:

完成此查询大约需要4秒钟。如果我把where降到一个id,那么它的速度将提高到170ms左右

如果您能就如何加快查询速度提出建议,我们将不胜感激

多谢各位

编辑

我能够根据里克·詹姆斯(接受答案)的建议提出解决方案。使用Union并去掉左连接和Distinct就成功了。与上面的4秒版本相比,这个新查询大约需要200毫秒

(SELECT  u.*, 
   (SELECT riu.registration_item_id 
       FROM registration_items_users riu 
       WHERE riu.user_id = u.id 
           AND riu.distributor_id = d.id 
           AND riu.registration_item_id = 21) as reg_id,
   d.id as dist_id
   FROM users u
   JOIN earned_points ep ON u.id = ep.user_id
   JOIN distributors d ON d.id = ep.distributor_id
       WHERE d.id IN (201,281,321,631,901,971,1211,1601,1611,1621,
            1631,1641,1651,1661,1671,1681,1691,1701,1711,1721,1731,
            1741,1751,1761,1771,1781,2281,2291,2401,2781,2801,2931))
   UNION
(SELECT  u.*, 
   (SELECT riu.registration_item_id 
       FROM registration_items_users riu 
       WHERE riu.user_id = u.id 
           AND riu.distributor_id = d.id 
           AND riu.registration_item_id = 21) as reg_id,
   d.id as dist_id
   FROM users u
   JOIN distributors d ON d.id = u.distributor_id
       WHERE d.id IN (201,281,321,631,901,971,1211,1601,1611,1621,
            1631,1641,1651,1661,1671,1681,1691,1701,1711,1721,1731,
            1741,1751,1761,1771,1781,2281,2291,2401,2781,2801,2931))
   UNION
(SELECT  u.*, 
   (SELECT riu.registration_item_id 
       FROM registration_items_users riu 
       WHERE riu.user_id = u.id 
           AND riu.distributor_id = d.id 
           AND riu.registration_item_id = 21) as reg_id,
   d.id as dist_id
   FROM users u
   JOIN distributors d ON d.id = u.additional_distributor_id
       WHERE d.id IN (201,281,321,631,901,971,1211,1601,1611,1621,
            1631,1641,1651,1661,1671,1681,1691,1701,1711,1721,1731,
            1741,1751,1761,1771,1781,2281,2291,2401,2781,2801,2931))

EXPLAIN
中,查看
u
行。它正在对大约6974行进行“表扫描”

除非“right”表是可选的,否则不要使用
LEFT

变为
接头
;这就是索引让你失望的地方。(
UNION ALL
UNION DISTINCT
快;选择有意义的一个。)

假设可以删除
左侧
,并假设
独立
可以从
选择
移动到
联合

SELECT  u.*, ri.id as reg_id, d.id as dist_id
    FROM  users u
    JOIN  earned_points ep ON u.id = ep.user_id  -- ep needed only for this
    JOIN  distributors d ON d.id = ep.distributor_id  -- This one line differs
    JOIN  registration_items_users riu ON u.id = riu.user_id
      AND  riu.distributor_id = d.id
      AND  riu.registration_item_id = 21
    JOIN  registration_items ri ON riu.registration_item_id = ri.id
    WHERE  d.id IN (201,281,321,631,901,971,1211,1601,1611,1621,
                1631,1641,1651,1661,1671,1681,1691,1701,1711,1721,1731,
                1741,1751,1761,1771,1781,2281,2291,2401,2781,2801,2931 
                   )
    UNION  DISTINCT 
SELECT  u.*, ri.id as reg_id, d.id as dist_id
    FROM  users u
    JOIN  distributors d ON d.id = u.distributor_id
    JOIN  registration_items_users riu ON u.id = riu.user_id
      AND  riu.distributor_id = d.id
      AND  riu.registration_item_id = 21
    JOIN  registration_items ri ON riu.registration_item_id = ri.id
    WHERE  d.id IN (201,281,321,631,901,971,1211,1601,1611,1621,
                1631,1641,1651,1661,1671,1681,1691,1701,1711,1721,1731,
                1741,1751,1761,1771,1781,2281,2291,2401,2781,2801,2931 
                   )
    UNION  DISTINCT 
SELECT  u.*, ri.id as reg_id, d.id as dist_id
    FROM  users u
    JOIN  distributors d ON d.id = u.additional_distributor_id
    JOIN  registration_items_users riu ON u.id = riu.user_id
      AND  riu.distributor_id = d.id
      AND  riu.registration_item_id = 21
    JOIN  registration_items ri ON riu.registration_item_id = ri.id
    WHERE  d.id IN (201,281,321,631,901,971,1211,1601,1611,1621,
                1631,1641,1651,1661,1671,1681,1691,1701,1711,1721,1731,
                1741,1751,1761,1771,1781,2281,2291,2401,2781,2801,2931 
                   ) ;
通常,在列之间展开数组不是一个好主意。这似乎就是
分销商的情况。而这场混乱可能就是这样的结果

编辑

更好的方法是将
ri
rui
从selects中取出,并将其转换为子查询。这里是要点;我没有精力写这一切:

SELECT x.*,
        ( SELECT ... ri and rui stuff ... ) AS reg_id
    FROM (
        --  from above, less the ri and rui stuff:
        SELECT ...
        UNION DISTINCT
        SELECT ...
        UNION DISTINCT
        SELECT ...
         ) AS x;

这不是意料之中的事吗?列表中有32个ID。32*170毫秒=5440毫秒。所以它的执行速度比线性的稍快。也就是说,IN()运算符可能会很慢。你可以尝试将ID列表转储到一个临时表中,加入临时表并在表上创建索引。我以前没做过临时表格。你能给我指一下正确的方向吗?ThanksI会先尝试索引,它们可以让临时表mootI觉得我已经拥有了所有表所需的索引。你对我遗漏的东西有什么建议吗?你有什么索引?您应该查看执行计划,以获得有关所需索引的提示。这是非常棒的东西!左连接是必需的。我将采纳你的建议,等我想出办法时再看一看。我会让你知道结果的。谢谢,你给我指明了正确的方向。我能够接受你所说的,并提出一个更快的问题。我能够删除所有左连接和独立连接。我将用我的查询更新我的问题,并将您的答案标记为已接受的解决方案。非常感谢。