繁体   English   中英

如何优化 SQL 查询?

[英]How can I optimize a SQL query?

SELECT *
FROM account a1 
LEFT JOIN account a2 ON a1.group_id>0 AND a2.app_id=0 AND a1.group_id=a2.group_id AND a1.id!=a2.id 
JOIN user_account_ref uar ON uar.account_id=a1.id OR (uar.account_id=a2.id AND uar.role>0) 
WHERE uar.user_id IN ($some_user_ids);

当我用WHERE a1.id IN ($some_account_ids)替换 where 子句时,查询速度很快,但在用户 ID 中查询却很慢。 我尝试使用子查询,但无法使其工作。

表架构如下所示:

---account---
id
app_id
group_id

---user_account_ref---
id
user_id
account_id
role

更多信息:

select * from user_account_ref where user_id IN (xxx)

速度很快,结果有 4 行。

SELECT * 
FROM account a1 
LEFT JOIN account a2 ON a1.group_id>0 AND a2.app_id=0 AND a1.group_id=a2.group_id AND a1.id!=a2.id

速度也很快,结果有 2000 多行。

请尝试这三个索引,看看它们是否能解决您的性能问题。 (然后查看解释计划以查看这些索引中的哪些未被使用并删除它们。)

create index idx1 on account (group_id, id, app_id);
create index idx2 on user_account_ref (user_id, account_id);
create index idx3 on user_account_ref (account_id, user_id);

idx1用于加速您的account自加入。 idx2idx3是 DBMS 快速加入user_account_ref表的两个提议。 希望 DBMS 会选择其中之一,从而更快地执行查询。

如果这些索引没有帮助,您可以尝试先只idx3 ,以便强制idx2 ,因为似乎用户的条件大大减少了要查看的行并且 DBMS 可能没有意识到这一点。

最后,您可以更新 MySQL 的表统计信息,以便 DBMS 更好地了解您的表。 祝你好运。

我终于使用了@Akina 建议的 UNION 查询。 我在group_id上添加了一个索引,这是@Thorsten Kettner 提醒的。 感谢你们俩。

这是我的新查询:

SELECT a.id, uar.* 
FROM account a
JOIN user_account_ref uar ON uar.account_id=a.id AND uar.status=0
WHERE uar.user_id IN (xxx)

UNION

SELECT a.id, uar.* 
FROM account a,
(
    SELECT DISTINCT ra.id, ra.group_id
    FROM account ra
    JOIN user_account_ref uar ON ra.id=uar.account_id and ra.app_id=0
    WHERE uar.user_id in (xxx) AND ra.group_id>0
) ra
JOIN user_account_ref uar ON uar.role>0
WHERE a.group_id=ra.group_id AND uar.account_id=ra.id AND uar.user_id IN (xxx);

如果这很快:

SELECT a1.*, a2.* 
FROM account a1 LEFT JOIN
     account a2
    ON a1.group_id > 0 AND 
       a2.app_id = 0 AND
       a1.group_id = a2.group_id AND
       a1.id <> a2.id;

然后使用两个left join

    SELECT a1.*, a2.*, COALESCE(uar1.role, uar2.role) as role
    FROM account a1 LEFT JOIN
         account a2
         ON a1.group_id > 0 AND 
            a2.app_id = 0 AND
            a1.group_id = a2.group_id AND
            a1.id <> a2.id LEFT JOIN
         user_account_ref uar1 AND uar2.role > 0
         ON uar1.account_id = a1.id LEFT JOIN
         user_account_ref uar2
         ON uar2.account_id = a2.id AND uar2.role > 0
WHERE uar1.user_id IN ($some_user_ids) OR
      uar2.user_id IN ($some_user_ids) ;

暂无
暂无

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

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