繁体   English   中英

带有子查询的 MYSQL 查询的性能问题

[英]Performance issue with my MYSQL query with subqueries

我的以下查询存在巨大的性能问题,我认为泄漏是什么,但不知道如何解决。

问题是内部选择遍历表中的所有记录,例如 200K,然后尝试选择并将过滤器应用于它,以便在第一轮中选择整个数据。

SELECT *
FROM (
    SELECT 
        ( SELECT GROUP_CONCAT(tp.login) login
              FROM tp
              WHERE tp.user_id = ue.user_id ) login, 
        u.email as email, 
        ue.fname as name 
    FROM user_extra ue
    LEFT JOIN users u ON u.id = ue.user_id 
) t
WHERE 
    email like '%sradesign.net@gmail.com%'
    OR fname like '%test%'
    OR login like '%461988%

测试我有没有搞错:

SELECT GROUP_CONCAT(tp.login) login,
       u.email as email, 
       ue.fname as name
FROM user_extra ue
JOIN users u ON u.id = ue.user_id    -- I doubt in LEFT
JOIN tp ON tp.user_id = ue.user_id
GROUP BY ue.fname,
         u.email
    -- , ue.user_id -- maybe needed, but I doubt
HAVING email like '%sradesign.net@gmail.com%'
    OR fname like '%test%'
    OR login like '%461988%

这是中间变体 - 它必须分为两个(或三个 - 取决于您的数据)单独的查询,稍后与 UNION 结合。


有时会发生一个用户没有任何登录名(tp 表中没有他的记录),但我想告诉他如果客户搜索词在 fname 的电子邮件中匹配,该怎么做? — 阿里·马哈茂迪

在这种情况下,必须使用外部连接 (LEFT JOIN) 连接此表。 – 秋菜

使用 left join 再次变得像之前的性能问题查询运行了 200 秒 – Ali Mahmoudi

正如我上面所说 - 这是中间变体。 如果它是正确的,那么让我们考虑到tp可能不存在的情况进行划分:

    SELECT GROUP_CONCAT(tp.login) login,
           u.email as email, 
           ue.fname as name
    FROM user_extra ue
    JOIN users u ON u.id = ue.user_id    -- I doubt in LEFT
    LEFT JOIN tp ON tp.user_id = ue.user_id
    WHERE u.email like '%sradesign.net@gmail.com%'
    GROUP BY ue.fname,
             u.email
UNION ALL
    SELECT GROUP_CONCAT(tp.login) login,
           u.email as email, 
           ue.fname as name
    FROM user_extra ue
    JOIN users u ON u.id = ue.user_id    -- I doubt in LEFT
    LEFT JOIN tp ON tp.user_id = ue.user_id
    WHERE ue.fname like '%test%'
    GROUP BY ue.fname,
             u.email
UNION ALL
    SELECT GROUP_CONCAT(tp.login) login,
           u.email as email, 
           ue.fname as name
    FROM user_extra ue
    JOIN users u ON u.id = ue.user_id    -- I doubt in LEFT
    JOIN tp ON tp.user_id = ue.user_id
    GROUP BY ue.fname,
             u.email
    HAVING login like '%461988%

测试其输出的正确性。

如果它将产生重复项,则将 UNION ALL 替换为 UNION DISTINCT。

  • 你似乎有一层额外的SELECTs 这会导致包含大量数据的额外临时表。
  • 不必要地使用LEFT会增加混乱并可能阻止某些优化。
  • 前导通配符防止使用索引。
  • OR很难优化。 但...

优化OR常见技巧:

( SELECT ... WHERE email like '%sradesign.net@gmail.com%' )
UNION DISTINCT
( SELECT ... WHERE fname like '%test%' )
UNION DISTINCT
( SELECT ... WHERE login like '%461988% )

但是,由于JOINsUNION可能不实用。

考虑使用FULLTEXT而不是LIKE

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM