0

我有一个有效的查询,但运行至少需要 3 秒,所以我认为它可能会更快。它用于填充新线程列表并显示每个线程中有多少未读帖子。我在将查询字符串放入$db->query_read(). 为了只从有效论坛中获取结果,$ids字符串最多包含 50 个值,以逗号分隔。

userthreadviews表已存在 1 周,其中大约有 9,500 行。我不确定我是否需要设置一个 cron 作业来定期清除一周以上的线程视图,或者我是否可以让它增长。

这是目前的查询:

SELECT 
    `thread`.`title` AS 'r_title', 
    `thread`.`threadid` AS 'r_threadid', 
    `thread`.`forumid` AS 'r_forumid', 
    `thread`.`lastposter` AS 'r_lastposter', 
    `thread`.`lastposterid` AS 'r_lastposterid', 
    `forum`.`title` AS 'f_title', 
    `thread`.`replycount` AS 'r_replycount', 
    `thread`.`lastpost` AS 'r_lastpost', 
    `userthreadviews`.`replycount` AS 'u_replycount', 
    `userthreadviews`.`id` AS 'u_id',
    `thread`.`postusername` AS 'r_postusername', 
    `thread`.`postuserid` AS 'r_postuserid' 
FROM 
    `thread` 
INNER JOIN 
    `forum` 
    ON (`thread`.`forumid` = `forum`.`forumid`) 
LEFT JOIN 
    (`userthreadviews`) 
    ON (`thread`.`threadid` = `userthreadviews`.`threadid` 
    AND `userthreadviews`.`userid`=$userid) 
WHERE 
    `thread`.`forumid` IN($ids) 
    AND `thread`.`visible`=1 
    AND `thread`.`lastpost`> time() - 604800
ORDER BY `thread`.`lastpost` DESC LIMIT 0, 30

连接post表的替代查询(仅显示用户发布的线程)实际上是两倍快,所以我认为这里必须有一些东西可以改变以加快速度。有人可以提供一些建议吗?

编辑:抱歉,我已将 EXPLAIN 放在备用查询前面。这是正确的输出:根据要求,这是 EXPLAIN SELECT 生成的输出: 解释查询

4

4 回答 4

2

看一下mysql的解释语句。它为您提供查询的执行计划。

知道计划后,您可以检查是否有计划中涉及的字段的索引。如果没有,请创建它们。

也许该计划揭示了有关如何以另一种方式编写查询的详细信息,从而使查询更加优化。

于 2012-09-16T17:30:03.160 回答
1

如果没有索引,请尝试索引表 forumid

于 2012-09-16T17:27:43.833 回答
1

要在连接/位置上没有索引(解释时使用的键 = NULL),这就是您的查询速度慢的原因。您应该以这种方式对它们进行索引:

CREATE INDEX thread_forumid_index ON thread(forumid);
CREATE INDEX userthreadviews_forumid_index ON userthreadviews(forumid);

文档在这里

于 2012-09-16T17:41:45.593 回答
0

建议:

  • 将条件从 WHERE 子句移到 JOIN 子句
  • 将带有条件的 JOIN 放在另一个 JOIN之前
  • 确保您有正确的索引并且它们正在查询中使用(创建您需要的索引......太多的索引可能和太少一样糟糕)

这是我对查询的建议:

SELECT 
    `thread`.`title` AS 'r_title',
    `thread`.`threadid` AS 'r_threadid',
    `thread`.`forumid` AS 'r_forumid',
    `thread`.`lastposter` AS 'r_lastposter',
    `thread`.`lastposterid` AS 'r_lastposterid',
    `forum`.`title` AS 'f_title',
    `thread`.`replycount` AS 'r_replycount',
    `thread`.`lastpost` AS 'r_lastpost',
    `userthreadviews`.`replycount` AS 'u_replycount',
    `userthreadviews`.`id` AS 'u_id',
    `thread`.`postusername` AS 'r_postusername',
    `thread`.`postuserid` AS 'r_postuserid' 
FROM
    `thread` 
    INNER JOIN (`forum`)
        ON ((`thread`.`visible` = 1)
        AND (`thread`.`lastpost` > $time)
        AND (`thread`.`forumid` IN ($ids))
        AND (`thread`.`forumid` = `forum`.`forumid`))
    LEFT JOIN (`userthreadviews`)
        ON ((`thread`.`threadid` = `userthreadviews`.`threadid`)
        AND (`userthreadviews`.`userid` = $userid))
ORDER BY
    `thread`.`lastpost` DESC
LIMIT
    0, 30

这些是很好的索引候选者:

- `forum`.`forumid`
- `userthreadviews`.`threadid`
- `userthreadviews`.`userid`
- `thread`.`forumid`
- `thread`.`threadid`
- `thread`.`visible`
- `thread`.`lastpost`

看来您已经有很多索引了……所以,请确保保留真正需要的索引并删除无用的索引。

于 2012-09-16T17:42:11.300 回答