0

動作するクエリがありますが、実行に少なくとも 3 秒かかるため、おそらく高速になると思います。新しいスレッドのリストを作成し、各スレッドに未読の投稿がいくつあるかを表示するために使用されます。に投げる前にクエリ文字列を生成します$db->query_read()。有効なフォーラムからのみ結果を取得するために$ids、カンマで区切られた最大 50 個の値の文字列です。

userthreadviewsテーブルは 1 週間存在し、約 9,500 行あります。1 週間以上前のスレッド ビューを定期的にクリアするために 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(ユーザーが投稿したスレッドのみを表示する) は、実際には 2 倍高速であるため、速度を上げるために変更できるものがここにあると思います。誰かアドバイスをいただけますか?

編集:申し訳ありませんが、代替クエリの前に EXPLAIN を配置しました。正しい出力は次のとおりです。要求どおり、EXPLAIN SELECT によって生成された出力は次のとおりです。 EXPLAINS クエリ

4

4 に答える 4

2

mysql の Explainステートメントを見てください。クエリの実行計画を提供します。

計画がわかったら、計画に関係するフィールドのインデックスを取得しているかどうかを確認できます。そうでない場合は、それらを作成します。

おそらく、計画は、クエリがより最適化されるように、別の方法でクエリを作成する方法についての詳細を明らかにします。

于 2012-09-16T17:30:03.160 に答える
1

インデックスが作成されていない場合は、テーブルforumidにインデックスを付けてみてください

于 2012-09-16T17:27:43.833 に答える
1

joins / where (explain で key = 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 に答える