12

2 億レコードのテーブル Foo と 1000 レコードのテーブル Bar があり、それらは多対 1 で接続されています。列 Foo.someTime および Bar.someField のインデックスがあります。また、Bar 900 レコードの someField は 1 で、100 レコードの someField は 2 です。

(1) このクエリはすぐに実行されます。

mysql> select * from Foo f inner join Bar b on f.table_id = b.table_id where f.someTime     between '2008-08-14' and '2018-08-14' and b.someField = 1 limit 20;
...
20 rows in set (0.00 sec)

(2) これには永遠に時間がかかります (唯一の変更は b.someField = 2 です):

mysql> select * from Foo f inner join Bar b on f.table_id = b.table_id where f.someTime     between '2008-08-14' and '2018-08-14' and b.someField = 2 limit 20;

(3) しかし、someTime の where 句を削除すると、すぐに実行されます。

mysql> select * from Foo f inner join Bar b on f.table_id = b.table_id where b.someField = 2 limit 20;
...
20 rows in set (0.00 sec)

(4) また、インデックスの使用を強制することで高速化できます。

mysql> select * from Foo f inner join Bar b force index(someField) on f.table_id = b.table_id where f.someTime     between '2008-08-14' and '2018-08-14' and b.someField = 2 limit 20;
...
20 rows in set (0.00 sec)

これがクエリ(2)の説明です(永遠にかかります)

+----+-------------+-------+--------+-------------------------------+-----------+---------+--------------------------+----------+-------------+
| id | select_type | table | type   | possible_keys                 | key       | key_len | ref                      | rows     | Extra       |
+----+-------------+-------+--------+-------------------------------+-----------+---------+--------------------------+----------+-------------+
|  1 | SIMPLE      | g     | range  | bar_id,bar_id_2,someTime      | someTime  | 4       | NULL                     | 95022220 | Using where |
|  1 | SIMPLE      | t     | eq_ref | PRIMARY,someField,bar_id      | PRIMARY   | 4       | db.f.bar_id              |        1 | Using where |
+----+-------------+-------+--------+-------------------------------+-----------+---------+--------------------------+----------+-------------+

(4)の説明は次のとおりです(フォースインデックスがあります)

+----+-------------+-------+------+-------------------------------+-----------+---------+--------------------------+----------+-------------+
| id | select_type | table | type | possible_keys                 | key       | key_len | ref                      | rows     | Extra       |
+----+-------------+-------+------+-------------------------------+-----------+---------+--------------------------+----------+-------------+
|  1 | SIMPLE      | t     | ref  | someField                     | someField | 1       |   const                  |       92 |             |
|  1 | SIMPLE      | g     | ref  | bar_id,bar_id_2,someTime      | bar_id    | 4       | db.f.foo_id              | 10558024 | Using where |
+----+-------------+-------+------+-------------------------------+-----------+---------+--------------------------+----------+-------------+

問題は、MySQL に正しいインデックスを使用するように教える方法です。クエリは ORM によって生成され、これら 2 つのフィールドだけに限定されません。また、クエリをあまり変更しないようにすることもお勧めします (ただし、内部結合がここに適合するかどうかはわかりません)。

アップデート:

mysql> create index index_name on Foo (bar_id, someTime);

その後、クエリ (2) は 0.00 秒で実行されます。

4

1 に答える 1