フォーラムを作成していて、少しフィードバックが必要でした。私は長い間プログラミングを行ってきましたが、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
どうもありがとうございました!