Ich habe Tabelle Foo mit 200 Millionen Datensätze und Tabelle Bar mit 1000 Datensätze, sie sind viele-zu-eins verbunden. Es gibt Indizes für die Spalten Foo.someTime und Bar.someField. Auch in Bar 900 Datensätze wurden von somefield 1, 100 haben somefield von 2.Mit Index auf innere Join-Tabelle in MySQL
(1) Diese Abfrage führt sofort:
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) Dieser dauert nur ewig (die einzige Änderung ist, 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) Aber wenn ich drop out where-Klausel auf Irgendwann, als er führt auch sofort:
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) Auch ich kann es beschleunigen, indem die Indexverwendung zwingt:
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)
Hier ist die auf Abfrage erklären (2) (das dauert ewig)
+----+-------------+-------+--------+-------------------------------+-----------+---------+--------------------------+----------+-------------+
| 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 |
+----+-------------+-------+--------+-------------------------------+-----------+---------+--------------------------+----------+-------------+
Hier ist die Erklärung auf (4) (welcher Kraftindex hat)
+----+-------------+-------+------+-------------------------------+-----------+---------+--------------------------+----------+-------------+
| 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 |
+----+-------------+-------+------+-------------------------------+-----------+---------+--------------------------+----------+-------------+
Also ist die Frage, wie man MySQL lehrt, richtigen Index zu verwenden? Die Abfrage wird von ORM generiert und ist nicht nur auf diese beiden Felder beschränkt. Und es wäre auch schön, die Abfrage nicht viel zu ändern (obwohl ich mir nicht sicher bin, ob der innere Join hier passt).
UPDATE:
mysql> create index index_name on Foo (bar_id, someTime);
, dass nach der Abfrage (2) ausführt, in 0,00 sec.
Bitte ** nie ** 'SELECT *' wenn Ihr SELECT irgendwelche Joins hat. Geben Sie stattdessen an, welcher Stern gemeint ist. Zum Beispiel ist 'SELECT f. * FROM foo f JOIN bar b ...' ok. Ansonsten ist nicht klar, welche Felder Ihr '*' holt, und es wird langsamer – mvp
Ich habe 'SELECT *' nur zum Beispiel verwendet, in realen DB generiert ORM die Abfrage ohne *. –