Я хочу сделать третью таблицу с той же структурой, что и вторая, но только с теми строками, для которых идентификаторы «от» и «до» находятся в первой таблице.
Это называется "denormalization", и, хотя для этого есть веские причины, это не считается хорошим дизайном базы данных, и его следует избегать.
Предположительно вы хотите сделать это, потому что ваши запросы настолько медленны. Итак, давайте посмотрим на ваш запрос.
SELECT *
FROM table2
WHERE from_id IN (SELECT id FROM table1)
AND to_id IN (SELECT id FROM table1)
Это может быть медленным, если MySQL должен делать полный просмотр таблицы table1, но это, кажется, достаточно умны, чтобы распознать его можно использовать индекс.
mysql> explain SELECT * FROM table2 WHERE from_id IN (SELECT id FROM table1) AND to_id IN (SELECT id FROM table1);
+----+-------------+--------+--------+---------------+---------+---------+---------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+--------+---------------+---------+---------+---------------------+------+-------------+
| 1 | SIMPLE | table2 | ALL | NULL | NULL | NULL | NULL | 4 | Using where |
| 1 | SIMPLE | table1 | eq_ref | PRIMARY | PRIMARY | 4 | test.table2.from_id | 1 | Using index |
| 1 | SIMPLE | table1 | eq_ref | PRIMARY | PRIMARY | 4 | test.table2.to_id | 1 | Using index |
+----+-------------+--------+--------+---------------+---------+---------+---------------------+------+-------------+
3 rows in set (0.00 sec)
Я думаю, что это может быть выражено лучше, явно запрашивая точный идентификатор в дополнительном запросе.
SELECT t2.*
FROM table2 t2
WHERE (SELECT 1 FROM table1 t1 WHERE t1.id = t2.from_id)
AND (SELECT 1 FROM table1 t1 WHERE t1.id = t2.to_id)
mysql> explain SELECT t2.* FROM table2 t2 WHERE (SELECT 1 FROM table1 t1 WHERE t1.id = t2.from_id) AND (SELECT 1 FROM table1 t1 WHERE t1.id = t2.to_id);
+----+--------------------+-------+--------+---------------+---------+---------+-----------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+--------+---------------+---------+---------+-----------------+------+-------------+
| 1 | PRIMARY | t2 | ALL | NULL | NULL | NULL | NULL | 4 | Using where |
| 3 | DEPENDENT SUBQUERY | t1 | eq_ref | PRIMARY | PRIMARY | 4 | test.t2.to_id | 1 | Using index |
| 2 | DEPENDENT SUBQUERY | t1 | eq_ref | PRIMARY | PRIMARY | 4 | test.t2.from_id | 1 | Using index |
+----+--------------------+-------+--------+---------------+---------+---------+-----------------+------+-------------+
3 rows in set (0.00 sec)
Трудно сказать, какой из них будет быстрее, у меня нет данных. До тех пор, пока table2.from_id, table2.to_id и t1.id индексируются, и они должны быть до тех пор, пока они будут правильно объявлены как внешние и первичные ключи, вы должны быть в порядке.
Если это еще не достаточно быстро, вместо денормализации я бы предложил вам create a view или временную таблицу или query cache. Они могут эффективно кэшировать запрос без необходимости денормализации. Выбор, который вы выбираете, зависит от того, насколько часто ваши данные обновляются и насколько чувствительны ваши приложения к изменениям.
Это сработало отлично - спасибо! Прошел от 24 до 175 секунд. –
99,8% улучшение;) На самом деле, индекс получает кредит на это. –