[英]How can I optimize this slow sql query?
我有一个约有40万行的用户表,并且在与其他表进行多个JOINS时需要检索其中一些(最大100行)。 (使用mysql)
我的问题是查询当前的执行时间约为800毫秒(获取46毫秒)。 我的目标是优化查询以减少执行时间。
我的初始查询如下:
SELECT iduser, imageurl, birthdate, active, last_active, created, gender_idgender, orientation_idorientation, region_idregion, moji.moji_idmoji as moji_idmoji, status.value as status, requests.value as requestsRecv, requestssent.value as requestsSent, username.value as username, likecount.value as likeCount, reportcount.value as reportCount
FROM user u
JOIN user_has_moji moji ON ( u.iduser = moji.user_iduser )
JOIN user_has_data status ON ( u.iduser = status.user_iduser AND status.datatype_iddatatype = 1 )
JOIN user_has_data requests ON ( u.iduser = requests.user_iduser AND requests.datatype_iddatatype = 3 )
JOIN user_has_data requestssent ON ( u.iduser = requestssent.user_iduser AND requestssent.datatype_iddatatype = 4 )
JOIN user_has_data username ON ( u.iduser = username.user_iduser AND username.datatype_iddatatype = 5 )
JOIN user_has_data likecount ON ( u.iduser = likecount.user_iduser AND likecount.datatype_iddatatype = 6 )
JOIN user_has_data reportcount ON ( u.iduser = reportcount.user_iduser AND reportcount.datatype_iddatatype = 7 )
WHERE banned = 0 AND active = 1 AND u.reviewstatus_idreviewstatus = 3 AND DATEDIFF(last_active,'2017-03-03 10:06:36') >=0 AND DATEDIFF(birthdate, '1999-03-03 15:06:36') >= 0 AND DATEDIFF(birthdate, '1967-03-03 15:06:36') <= 0 ORDER BY last_active DESC LIMIT 100
我认为执行时间长的原因是它必须在进行查询之前将整个用户表与其他表联接在一起,因此我尝试了这种方法:
SELECT iduser, imageurl, birthdate, active, last_active, created, gender_idgender, orientation_idorientation, region_idregion, moji.moji_idmoji as moji_idmoji, status.value as status, requests.value as requestsRecv, requestssent.value as requestsSent, username.value as username, likecount.value as likeCount, reportcount.value as reportCount
FROM ( SELECT * FROM user WHERE banned = 0 AND active = 1 AND reviewstatus_idreviewstatus = 3 AND DATEDIFF(last_active,'2017-03-03 10:01:30') >=0 AND DATEDIFF(birthdate, '1999-03-03 15:01:30') >= 0 AND DATEDIFF(birthdate, '1967-03-03 15:01:30') <= 0 ORDER BY last_active DESC LIMIT 100 ) as u
JOIN user_has_moji moji ON ( u.iduser = moji.user_iduser )
JOIN user_has_data status ON ( u.iduser = status.user_iduser AND status.datatype_iddatatype = 1 )
JOIN user_has_data requests ON ( u.iduser = requests.user_iduser AND requests.datatype_iddatatype = 3 )
JOIN user_has_data requestssent ON ( u.iduser = requestssent.user_iduser AND requestssent.datatype_iddatatype = 4 )
JOIN user_has_data username ON ( u.iduser = username.user_iduser AND username.datatype_iddatatype = 5 )
JOIN user_has_data likecount ON ( u.iduser = likecount.user_iduser AND likecount.datatype_iddatatype = 6 )
JOIN user_has_data reportcount ON ( u.iduser = reportcount.user_iduser AND reportcount.datatype_iddatatype = 7 )
认为需要连接的行数将大大减少,因此减少了执行时间。 这项更改似乎有所帮助,但查询量仍然过低。
有人可以看到执行缓慢的其他原因吗?
您的响应时间非常合理,因此您的表似乎已正确索引。 但是,让我们看一下WHERE
子句(我添加了假定的表别名):
WHERE u.banned = 0 AND u.active = 1 AND
u.reviewstatus_idreviewstatus = 3 AND
DATEDIFF(u.last_active,'2017-03-03 10:06:36') >=0 AND
DATEDIFF(u.birthdate, '1999-03-03 15:06:36') >= 0 AND
DATEDIFF(u.birthdate, '1967-03-03 15:06:36') <= 0
首先,删除datediff()
并进行简单比较。 我想你想要这个:
WHERE u.banned = 0 AND u.active = 1 AND
u.reviewstatus_idreviewstatus = 3 AND
u.last_active >= '2017-03-03 10:06:36' AND
u.birthdate >= '1999-03-03 15:06:36' AND
u.birthdate <= '1967-03-03 15:06:36'
我对最后三个条件有些怀疑,但是使用datediff()
会造成混淆。 这就是简单比较更好的原因之一。
您需要快速找到这些行,建议使用以下两个索引之一:
users(banned, active, reviewstatus_idreviewstatus, last_active, birthdate)
要么
users(banned, active, reviewstatus_idreviewstatus, birthdate, last_active)
这取决于哪些因素会减少数据量。 我的猜测是last_active
更重要。 还要注意,前三个键可以是任意顺序,只要它们是前三个即可。
这可能会有所帮助,但我怀疑您会看到惊人的改进。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.