mysql - 优化我的 MySQL 查询

标签 mysql sql query-optimization

我正在创建一个论坛,需要一些反馈。我已经编程很长时间了,但我对 MySQL 相当了解,并且想知道我这样做是否正确。

这是我用来输出所选论坛的主题索引的查询。我试图在单个查询中收集所有信息,而不是仅收集主题信息,然后在每个循环中收集一次帖子和成员信息,总共 35 个单独的查询(每个查询一个主题)。清楚了吗?

基本上,它可以工作。即使只有 300-400 个主题,速度也有点慢(大约 1 秒)。

我使用了分析,发现最耗时的操作是: 复制到临时表: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

非常感谢!

最佳答案

要做的第一件事是查看您的解释计划并将其发布。另一件突出的事情是您实际上不想执行大量子查询。

首先,看看您的第一次加入

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`

关于mysql - 优化我的 MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14822047/

相关文章:

sql - (self) 按时间间隔加入

java - 使用 mysql-connector-java-5.1.24 将 Java 连接到 MySQL

mysql 参数添加不评估

mysql - 执行用户迁移时出错

sql - 使用嵌套循环提高 SQL 查询的性能 - PostgreSQL

php - Magento:如何将商店设置转移到默认范围?

sql - 细数一对一的关系

mysql - 通过 localhost 连接 MySQL 不工作但 127.0.0.1 工作

php - MySQL时间间隔查询重载服务器

sql-server - 您如何确保新索引不会减慢查询速度?