友達が最も閲覧したページを表示できる機能を提供しようとしています。friends テーブルには 570 万行、views テーブルには 530 万行あります。現時点では、これら 2 つのテーブルに対してクエリを実行し、ある人の友人によって最も多く閲覧された 20 のページ ID を見つけたいだけです。
私が今持っているクエリは次のとおりです。
SELECT page_id
FROM `views` INNER JOIN `friendships` ON friendships.receiver_id = views.user_id
WHERE (`friendships`.`creator_id` = 143416)
GROUP BY page_id
ORDER BY count(views.user_id) desc
LIMIT 20
そして、説明は次のようになります。
+----+-------------+-------------+------+-----------------------------------------+---------------------------------+---------+-----------------------------------------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------+------+-----------------------------------------+---------------------------------+---------+-----------------------------------------+------+----------------------------------------------+
| 1 | SIMPLE | friendships | ref | PRIMARY,index_friendships_on_creator_id | index_friendships_on_creator_id | 4 | const | 271 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | views | ref | PRIMARY | PRIMARY | 4 | friendships.receiver_id | 11 | Using index |
+----+-------------+-------------+------+-----------------------------------------+---------------------------------+---------+-----------------------------------------+------+----------------------------------------------+
ビュー テーブルには (user_id, page_id) の主キーがあり、これが使用されていることがわかります。友情テーブルには、(receiver_id、creator_id) のプライマリ キーと、(creator_id) のセカンダリ インデックスがあります。
group by と limit を指定せずにこのクエリを実行すると、この特定のユーザーに対して約 25,000 行になります。これは一般的な値です。
最新の実際の実行では、このクエリの実行に 7 秒かかりました。これは、Web アプリで適切な応答を得るには長すぎます。
私が疑問に思っていることの 1 つは、セカンダリ インデックスを (creator_id、receiver_id) に調整する必要があるかどうかです。ただし、それによってパフォーマンスが大幅に向上するかどうかはわかりません。この質問への回答に応じて、今日試してみます。
クエリを書き直して非常に高速にする方法がわかりますか?
更新:さらにテストを行う必要がありますが、データベースでグループ化とソートを行わず、後でルビーで行うと、私の厄介なクエリがうまく機能するようです。全体的な時間ははるかに短く、約 80% 短縮されているようです。おそらく私の初期のテストには欠陥があったのでしょう - しかしこれは間違いなくもっと調査する必要があります. それが本当なら、wtf は Mysql を実行していますか?