実現したいこと
リザルトテーブルとユーザーテーブルがあり、これらのテーブルをユーザーIdで結合したときになぜかこの2つのテーブルをインデックスを使わずに結合しようとしてしまいます。
ユーザーテーブルには主キーがあり、リザルトテーブルにはユーザーIdにインデックスが貼られています。
考えられる原因はなんでしょうか?
これは、リザルトテーブルのユーザーIdの照合順序をutf8mb3_general_ciからutf8mb4_binに変更したときに発生しました。
前提
MySQLで2つのテーブルを実装しました。
1つはユーザーテーブルで、カラムにはユーザーId、ユーザー名があります。主キーはユーザーIdです。
もう1つはリザルトテーブルで、これはゲームのスコアを記録するためのテーブルです。カラムにはId(自動採番)、ユーザーId、スコアがあります。主キーはId、ユーザーIdにインデックスが貼られています。
具体的には、以下のようなテーブル構成になっています。
ユーザーテーブル
名前 | タイプ | 照合順序 | 属性 | Null | デフォルト値 | コメント | その他 |
---|---|---|---|---|---|---|---|
ユーザーId | varchar(30) | utf8mb4_bin | いいえ | なし | |||
ユーザー名 | varchar(80) | utf8mb4_0900_ai_ci | いいえ | なし |
リザルトテーブル
名前 | タイプ | 照合順序 | 属性 | Null | デフォルト値 | コメント | その他 |
---|---|---|---|---|---|---|---|
Id | int | いいえ | なし | AUTO_INCREMENT | |||
ユーザーId | varchar(30) | utf8mb4_bin | いいえ | ||||
スコア | int | いいえ | なし |
発生している問題・エラーメッセージ
以下のSQLの実行に10秒以上かかってしまう。
SELECT Id, スコア, ユーザー.ユーザー名 FROM リザルト INNER JOIN ユーザー ON リザルト.ユーザーId = ユーザー.ユーザーId ORDER BY Id DESC LIMIT 50
EXPLAINの結果
id | select_type | table | partitions | type | possible_keys | keys | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | ユーザー | NULL | ALL | PRIMARY | NULL | NULL | NULL | 10909 | 100.00 | Using temporary; Using filesort |
1 | SIMPLE | リザルト | p0,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15 | ref | ユーザーId | ユーザーId | 122 | データベース名.ユーザー.ユーザーId | 38 | 100.00 | NULL |
INNER JOINをなくすと0.0006秒で処理が完了する。
SELECT Id, スコア FROM リザルト ORDER BY Id DESC LIMIT 50
試したこと
2つのテーブルに対してphpMyAdminを用いてテーブルの分析、テーブルをチェックする、テーブルのデフラグ、テーブルを最適化する、を実施しました。
また、リザルトテーブルのユーザーIdの照合順序をutf8mb3_general_ciに戻しても、上記のSQLに10秒以上かかるようになってしまいました。
補足情報
ユーザーテーブルのレコード数は約10,000
リザルトテーブルのレコード数は約4,000,000です。

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。