次のクエリは、ユーザーによる未読メッセージのリストを受信することを目的としています。これには3つのテーブルrecipients
が含まれます。ユーザーとメッセージIDの関係messages
、メッセージ自体、およびmessage_readers
どのユーザーがどのメッセージを読んだかを示すリストが含まれます。
クエリには確実に4.9秒かかります。これはパフォーマンスに深刻な悪影響を及ぼします。データベースが最終的に数桁大きくなることを期待しているため、特に心配です。確かに、これは本質的に重いクエリですが、データセットは小さく、直感的にははるかに高速であるように見えます。サーバーには十分なメモリ(32GB)があるため、データベース全体を常にRAMにロードする必要があり、ボックス上で他に何も実行されていません。
テーブルはすべて小さいです:
recipients: 23581
messages: 9679
message_readers: 2685
クエリ自体:
SELECT
m.*
FROM
messages m
INNER JOIN recipients r ON r.message_id = m.id
LEFT JOIN message_readers mr ON mr.message_id = m.id
WHERE
r.id = $user_id
AND (mr.read_by_id IS NULL OR mr.read_by_id <> $user_id)
説明計画は非常に簡単です。
+----+-------------+-------+--------+-----------------------------------+-----------------------------------+---------+--------------------------------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-----------------------------------+-----------------------------------+---------+--------------------------------+-------+-------------+
| 1 | SIMPLE | r | ref | index_recipients_on_id | index_recipients_on_id | 768 | const | 11908 | Using where |
| 1 | SIMPLE | m | eq_ref | PRIMARY | PRIMARY | 4 | db.r.message_id | 1 | Using index |
| 1 | SIMPLE | mr | ALL | NULL | NULL | NULL | NULL | 2498 | Using where |
+----+-------------+-------+--------+-----------------------------------+-----------------------------------+---------+--------------------------------+-------+-------------+
にインデックスがありmessage_readers.read_by_id
ますが、IS NULL条件のため、実際には使用できないと思います。
以下を除くすべてのデフォルト設定を使用しています。
key_buffer=4G
query_cache_limit = 256M
query_cache_size = 1G
innodb_buffer_pool_size=12G
ありがとう!