我不确定如何使以下SQL查询更有效。现在,查询在一台非常快的服务器上花费了8到12秒,但是当用户尝试加载带有此代码的页面时,这对于网站而言并不足够快。它正在查看包含许多行的表,例如“Post”表有717,873行。基本上,查询列出了与用户所关注的内容相关的所有帖子(从最新到最旧)。
有没有办法通过仅根据PostTimeOrder获得最后20个结果总数来加快速度?
对于可以采取任何措施来改善这种情况,我们将非常感激或深入了解任何帮助。谢谢。
这是完整的SQL查询(大量嵌套):
public function checkCredentials($credentials, $userInterface $user)
...
$password = $credentials['_password'];
$login_format = 'DOMAIN\%s'; // this is the expected format in my case
$login_username = sprintf($login_format, $user);
...
try {
// try to bind with the username and provided password
$this->ldap->bind($login_username, $password);
} catch (\Symfony\Component\Ldap\Exception\ConnectionException $e) {
//return false;
throw new CustomUserMessageAuthenticationException('The submitted LDAP password is invalid.');
};
return true;
};
答案 0 :(得分:0)
将p.ID in (...)
谓词更改为具有相关子查询的存在谓词可能有帮助。此外,由于你的union的两半都是从Post表中提取的,并且可能返回几乎相同的记录,你可能能够通过左外连接到UserPostE
将两者合并为一个查询添加upe.PostID
不是OR
子句中的WHERE
条件。 UserFollowing
仍然会加入UPE。如果您希望同一帖子记录两次upe.PostEchoTime
一次,p.PostCreationTime
一次PostTimeOrder
,则需要保留UNION ALL
SELECT
DISTINCT -- <<=- May not be needed
p.Id
, UNIX_TIMESTAMP(p.PostCreationTime) AS PostCreationTime
, p.Content AS Content
, p.Bu AS Bu
, p.Se AS Se
, UNIX_TIMESTAMP(coalesce( upe.PostEchoTime
, p.PostCreationTime)) AS PostTimeOrder
FROM Post p
LEFT JOIN UserPostE upe
INNER JOIN UserFollowing uf
on (upe.UserId = uf.FollowedId AND
(uf.FollowingId = '100' OR
upe.UserId = '100'))
on p.Id = upe.PostId
WHERE upe.PostID is not null
or exists (SELECT 1
FROM PostCreator pc
WHERE pc.PostId = p.ID
and pc.UserId = '100'
or exists (SELECT 1
FROM UserFollowing uf
WHERE uf.FollowedId = pc.UserID
and uf.FollowingId = '100')
)
OR exists (SELECT 1
FROM PostUserMentions pum
WHERE pum.PostId = p.ID
and pum.UserId = '100'
or exists (SELECT 1
FROM UserFollowing uf
WHERE uf.FollowedId = pum.UserId
and uf.FollowingId = '100')
)
OR exists (SELECT 1
FROM SStreamPost ssp
WHERE ssp.PostId = p.ID
and exists (SELECT 1
FROM SStreamFollowing ssf
WHERE ssf.SStreamId = ssp.SStreamId
and ssf.UserId = '100')
)
OR exists (SELECT 1
FROM PostSMentions psm
WHERE psm.PostId = p.ID
and exists (SELECT
FROM StockFollowing sf
WHERE sf.StockId = psm.StockId
and sf.UserId = '100' )
)
ORDER BY PostTimeOrder DESC
也可以重写from部分以使用带有相关子查询的exists子句:
FROM Post p
LEFT JOIN UserPostE upe
on p.Id = upe.PostId
and ( upe.UserId = '100'
or exists (select 1
from UserFollowing uf
where uf.FollwedID = upe.UserID
and uf.FollowingId = '100'))
答案 1 :(得分:0)
IN ( SELECT ... )
变为JOIN .. ON ...
(见下文)OR
变为UNION
(见下文)SStreamFollowing
?按照http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table IN
的示例:
SELECT ssp.PostId
FROM SStreamPost ssp
WHERE (ssp.SStreamId IN (
SELECT ssf.SStreamId
FROM SStreamFollowing ssf
WHERE ssf.UserId = '100' ))
- &GT;
SELECT ssp.PostId
FROM SStreamPost ssp
JOIN SStreamFollowing ssf ON ssp.SStreamId = ssf.SStreamId
WHERE ssf.UserId = '100'
所有WHERE
的大INs
变为类似
JOIN ( ( SELECT pc.PostId AS id ... )
UNION ( SELECT pum.PostId ... )
UNION ( SELECT ssp.PostId ... )
UNION ( SELECT psm.PostId ... ) )
获取您可以做的那些建议,然后在需要时再回来寻求更多建议。并随身携带SHOW CREATE TABLE
。