Mysql 如何优化SQL查询?
当我将where子句替换为Mysql 如何优化SQL查询?,mysql,sql,sql-optimization,Mysql,Sql,Sql Optimization,当我将where子句替换为where a1.id IN($some\u account\u id)时,查询速度很快,但在用户id中查询速度很慢。我尝试使用子查询,但无法使其工作 表架构如下所示: 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 u
where a1.id IN($some\u account\u id)
时,查询速度很快,但在用户id中查询速度很慢。我尝试使用子查询,但无法使其工作
表架构如下所示:
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);
更多信息:
---account---
id
app_id
group_id
---user_account_ref---
id
user_id
account_id
role
速度快,结果中有4行
select * from user_account_ref where user_id IN (xxx)
也很快,结果中有2000多行。请尝试这三个索引,看看它们是否解决了性能问题。(然后查看解释计划,看看哪些索引没有被使用,并删除它们。)
select * from user_account_ref where user_id IN (xxx)
idx1
用于加速您的帐户
自加入idx2
和idx3
是提供给DBMS的两个选项,用于快速加入user\u account\u ref
表。希望DBMS能够从中选择一个,从而更快地执行查询
如果这些索引没有帮助,您可以先尝试只删除idx3
,以便强制执行idx2
,因为用户的条件似乎大大减少了要查看的行,DBMS可能不知道这一点
最后,您可以更新MySQLs表统计信息,以便DBMS更好地了解您的表。祝你好运。我终于使用了@Akina建议的联合查询。我在
组id
上添加了一个索引,由@Thorsten Kettner提醒。谢谢你们两位
以下是我的新查询:
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);
如果速度很快:
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;
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) ;