【发布时间】:2020-10-16 23:24:11
【问题描述】:
我正在开发一个 QnA 应用程序,在该应用程序中我加载了用户特定的数据,例如用户是否对帖子进行了投票,或者是否关注了撰写帖子的用户。我目前的方法如下-
SELECT tbl_answer.*, tbl_user.username, tbl_user.dp_62, tbl_personal_info.full_name, tbl_personal_info.tagline,
IFNULL(followers.following, 0) following,
IFNULL(voters.voted, 0) voted
FROM tbl_answer
LEFT JOIN tbl_user ON tbl_user.user_id = tbl_answer.user_id
LEFT JOIN tbl_personal_info ON tbl_personal_info.user_id = tbl_answer.user_id
LEFT JOIN (
SELECT answer_id, IF(a_vote_up = 1, 1, a_vote_down * -1) AS voted
FROM tbl_answer_vote
WHERE user_id = $user_id //Retrieved from the token beforehand
) voters ON voters.answer_id = tbl_answer.answer_id
LEFT JOIN (
SELECT following_id, 1 AS following
FROM tbl_user_follow
WHERE follower_id = $user_id
) followers ON followers.following_id = tbl_answer.user_id
WHERE question_id = ?
ORDER BY selected DESC,
under_review ASC,
answer_up_vote DESC,
answer_id ASC,
answer_down_vote ASC
LIMIT 30
它似乎没有那么快,有时需要超过 4 秒。答案表有近一百万个条目。 在最短的时间内达到这种结果的一般过程是什么? 如果有任何需要考虑的因素,我会在我的 API 后端使用 Laravel。
感谢您的指导。
【问题讨论】:
-
问题是您只有单列索引,而 where 条件将由多列索引提供。 MySQL 试图通过使用索引合并来弥补,但这并不像使用单个索引那样高效。
-
“一般流程”是为了避免不必要的工作。为什么在这里使用子查询?你的实际问题是什么?如果您真的要求“一般流程”,我将结束投票,因为“需要更多的 fokus”。
-
我用 IF-EXISTS 替换了关于投票、关注和书签的连接,这将时间减少到毫秒。在这里发布之前应该尝试过。
-
在考虑该查询之前,我们需要知道哪个列在哪个表中。您必须提供资格和/或
SHOW CREATE TABLE。它对WHERE question_id = ? ORDER BY selected DESC, under_review ASC, answer_up_vote DESC, answer_id ASC, answer_down_vote ASC产生了很大的不同
标签: mysql sql laravel performance