我想创建第三个表,其结构与第二个表相同,但只有第一个表中的“来自”和“到”ID 的行。
这被称为“非规范化”,虽然这样做有正当理由,但它不被认为是好的数据库设计,应该避免。
大概你想这样做是因为你的查询太慢了。因此,让我们看看您的查询。
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)
我认为可以通过在子查询中明确询问确切的 ID 来更好地表达它。
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 被索引,只要它们被正确声明为外键和主键,你应该没问题。
如果它仍然不够快,而不是非规范化,我建议您创建一个视图或临时表或查询缓存。这些可以有效地缓存查询,而不必进行非规范化。您选择哪一种取决于您的数据更新频率以及您的应用程序对更改的敏感程度。