[英]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
自加入。 idx2
和idx3
是 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.