我正在创建一个论坛,需要一些反馈。我已经编程了很长时间,但我对MySQL很了解,并且想知道我是否正确地做了这个。
这是我用来输出所选论坛的thr主题索引的查询。我试图在单个查询中收集所有信息,而不是仅收集主题信息,然后在每个循环中收集一次帖子和成员信息,共计35个单独查询(每个查询一个主题)。那是清楚的吗?
基本上,它有效。即使只有300-400个主题,它也有点慢(大约1秒)。
我使用了分析,并收集了最耗时的操作: 复制到tmp表:0.538037 发送数据:0.206218 复制到组表:0.137549
编辑: 每当有人进入页面时,查询将运行一次(根据站点活动判断,每小时约200-300次)。我打算一次检索大约4000-5000行。
我的问题是:这是最好的方法吗?我可以做些什么来优化这个查询?或者我最好在循环中执行大量较小的查询?
$user_id: id of the user
$forum_id: id of the selected forum
SELECT
# Topic records
`topics`.*,
# First Post
GROUP_CONCAT(`posts`.`id`) AS `post_id`, # All post ids
`posts`.`post` AS `post_first_msg`,
`posts`.`date` AS `post_first_date`,
`posts`.`member` AS `post_first_member`,
# First member
`members`.`id` AS `member_id`,
`members`.`username` AS member_username,
# Returns last 3 members' id
SUBSTRING_INDEX(
GROUP_CONCAT(`members`.`id` ORDER BY `posts`.`date` DESC SEPARATOR '\\\\'), '\\\\', 3
) AS member_last_id,
# Returns last 3 members' username
SUBSTRING_INDEX(
GROUP_CONCAT(`members`.`username` ORDER BY `posts`.`date` DESC SEPARATOR '\\\\'), '\\\\', 3
) AS member_last_username,
# Get last viewed topic id
`member_topic_lastview`.`lastview` AS `lastview`
FROM
`topics`
# Returns the `posts` table in ASC order
JOIN (
SELECT *
FROM `posts`
ORDER BY `posts`.`date` ASC
) AS `posts` ON `posts`.`topic` = `topics`.`id`
# Member table, only the columns needed
JOIN (
SELECT
`members`.`id`,
`members`.`username`
FROM `members`
) AS `members` ON `members`.`id` = `posts`.`member`
# Forum table, containing the forum info
LEFT JOIN `forum` ON `forum`.`id` = `topics`.`forum`
# Table containing the latest viewed post id of each topic
LEFT JOIN (
SELECT *
FROM `member_topic_lastview`
WHERE `member_topic_lastview`.`member` = '$user_id'
) AS `member_topic_lastview` ON `member_topic_lastview`.`topic` = `topics`.`id`
WHERE
`forum` > $forum_id
GROUP BY
`topics`.`id`
ORDER BY
`topics`.`sticky` DESC,
MAX(`posts`.`date`) DESC
LIMIT 35
非常感谢!
答案 0 :(得分:2)
首先要做的是查看您的解释计划并发布。另一件突出的事情是你真的不想做很多子查询。
只是为了开始,看看你的第一次加入
FROM
`topics`
# Returns the `posts` table in ASC order
JOIN (
SELECT *
FROM `posts`
ORDER BY `posts`.`date` ASC
) AS `posts` ON `posts`.`topic` = `topics`.`id`
如果你只是写它,这可能要快得多:
FROM
`topics`
# Returns the `posts` table in ASC order
JOIN `posts` ON `posts`.`topic` = `topics`.`id`