MySQL GroupWise 100万行テーブルの最大パフォーマンス上の問題
-
13-12-2019 - |
質問
私は、膨大な数の投稿がある非常にアクティブなフォーラムのパフォーマンスを向上させるための簡単な方法を見つけようとしています、そしてMySQLは、テーブルをメモリ内で並べ替えることができず、インデックスを最大限に活用していないようではないようです。< / P>
この単純なクエリは、ユーザーがユーザーが任意のトピックの最新の投稿を見つけて、(後でTOPIC_TIMEを比較することによって)
SELECT p.*, MAX(post_time) as post_time FROM forum_posts AS p
WHERE p.poster_id = '1' AND p.post_status = '0'
GROUP BY p.topic_id
ORDER BY post_time DESC
LIMIT 50
.
シンプルな平らなテーブルは
のように見えますpost_id | poster_id | topic_id | post_status | post_time | post_text
.
しかし、それは百万の投稿があるときにパフォーマンスが離れています、そしてユーザー自身は何千もの投稿を持っています。 MySQLは、テーブルをメモリ内のテーブルをソートしなくても、スキャンする行が多すぎます。それはその時点でCPUをスパイクし、他のみんなを遅くしているので、許容できないIMHOであるRealWorldの使用で最大3秒かかることがあります。
もちろんの索引の組み合わせを作ることができますが、MySQLは主に
のコンボを使うのが好きですposter_id + post_time
.
だから1人のユーザーの50kの投稿を百万人のうちに投稿するだけで、TOPIC_IDと並べ替えによるグループ化を開始します。 Index Mixにtopic_idを変更することは、索引フィールドの順序であるかもしれませんが、パフォーマンスを助けるようには見えませんか?
代わりに同等の結合を書かせようとしましたので、複数の索引を使用できますが、Post_StatusとPosterによってフィルタリングされなければならないという事実に問題があります。
私は、少なくとも最初の数ページで、Post_timeによるインデックスを介してデータを最初に並べ替えてから、降順でユーザーのDistint Topic_idをピッキングすることができる場合は、少なくとも最初の数ページについては、より速くなると考えていました。注文。私は副問合せが必要であり、50kの結果副照会がより良くなるとわからないと思いますが、まだ一時的な表が必要であることがわかります。
もちろん基本的な解決策は、各トピックの各ユーザーのMAX POST_TIMEを格納するだけのテーブルがありますが、他の解決策が見つからない限り、これは変化の大きすぎることです。提案をありがとうございました!
RealWorldの追加と説明:
遅いログ
# Query_time: 2.751334 Lock_time: 0.000056 Rows_sent: 40 Rows_examined: 48286
SELECT p.*, MAX(post_time) as post_time FROM forum_posts AS p WHERE p.poster_id = '2' AND p.post_status = '0' GROUP BY p.topic_id ORDER BY post_time DESC LIMIT 7000, 40;
.
説明
select_type table type possible_keys key key_len ref rows Extra
SIMPLE p ref poster_time poster_time 4 const 27072 Using where; Using temporary; Using filesort
. 解決
まず、クエリを決定するためにクエリを修正します。
SELECT p.topic_id,
MAX(post_time) as post_time
FROM forum_posts AS p
WHERE p.poster_id = '1' AND p.post_status = '0'
GROUP BY p.topic_id
ORDER BY post_time DESC
LIMIT 50 ;
.
(post_status, poster_id, topic_id, post_time)
にインデックスを追加した後に試してみてください。