0

フォーラムを作成していて、少しフィードバックが必要でした。私は長い間プログラミングを行ってきましたが、MySQL についてはかなり知っていて、これが正しく行われているのか疑問に思っていました。

これは、選択したフォーラムのトピック インデックスを出力するために使用しているクエリです。トピック情報のみを収集し、すべてのループで毎回投稿とメンバー情報を収集するのではなく、1 つのクエリですべての情報を収集しようとしています。それは明らかですか?

基本的に、それは機能します。トピック数が 300 ~ 400 しかない場合でも、少し遅くなります (約 1 秒)。

私はプロファイリングを使用して、最も時間がかかるアクションを収集しました: tmp テーブルへのコピー: 0.538037 データの送信: 0.206218 グループ テーブルへのコピー: 0.137549

編集:クエリは、誰かがページに入るたびに1回実行されます(サイトのアクティビティから判断すると、1時間に約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

どうもありがとうございました!

4

1 に答える 1

2

最初にすべきことは、説明計画を見て、それを投稿することです。もう 1 つの際立った点は、実際には多くのサブクエリを実行したくないということです。

始めに、最初の参加を見てください

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`
于 2013-02-11T22:26:29.673 に答える