用户表有
id, email, password, gender, dob
等。性别默认为null。我有另一张表user_gender
,其中包含first_name
和gender
。我的SQL查询是从User
获取用户,并根据User_Gender
从first_name
中选择性别。用户表非常庞大,大约有300,000多行。我正在运行下面提到的查询,但这花费了太多时间。如何优化此查询? -
select
count(*)
from user u
left outer join user_gender ug on ug.name =
case when locate(' ', u.name) > 0 then
substring(u.name, 1,locate(' ', u.name))
else
u.name
end
where
ug.gender != 'mf' and u.gender is null
答案 0 :(得分:6)
首先我建议完全重组。 300000行开始达到“中等数据集”大小......
NULL
... 其次,您必须应用索引,并check your queries' execution plans确保对其进行适当优化。
答案 1 :(得分:3)
首先处理这两个表的设计将有助于您更好地解决性能问题。 性能问题发生在您的join子句中:
找到('',u.name)> 0然后子串(u.name,1,locate('', u.name))否则u.name end
为User表使用主键(user_id)并在user_gender表上显示并相应地加入。
OR
由于您可能正在使用旧版数据库设计而无法添加或使用user_id字段,因此您可以使用临时first_name字段并使用您的join子句填充它
update users u set u.first_name = case when locate(' ', u.name)>0
then substring(u.name, 1,locate(' ',> u.name)) else u.name end
在此之后,您可以将查询重写为
select count(*) from user u left outer join user_gender ug
on ug.name=u.first_name
where ug.gender != 'mf' and u.gender is null
这将有助于您的查询运行得更快,但我建议第一个解决方案,无论如何添加/使用主键。
答案 2 :(得分:0)
我注意到的第一件事是查询编写不正确。或者,至少,它没有做你想要的。 !=
子句中的where
是“撤消”左外连接。我想你想在on
条款中找到它。
对于user_gender(firstname, gender)
的索引,我认为这个版本应该很快运行:
select count(*)
from (select u.*,
(case when locate(' ', u.name) > 0 then substring(u.name, 1,locate(' ', u.name))
else u.name
end) as FirstName
from user u
) u
where not exists (select 1 from user_gender ug where ug.name = u.FirstName and ug.gender <> 'mf')
应该是用户表,计算名字,并检查索引以查看是否存在性别。