And*_*nko 0 mysql sql indexing join query-optimization
tt - 是一个映射表。 tt结构是
表_1 | 表_2 | 表3
SELECT t1.foo1, t2.foo2, t3.foo3 FROM tt
JOIN table1 t1 ON tt.table_1 = t1.id
JOIN table2 t2 ON tt.table_2 = t2.id
JOIN table3 t3 ON tt.table_3 = t3.id
WHERE t2.value = 'test'
Run Code Online (Sandbox Code Playgroud)
该指数是否有意义并且会发挥作用tt?综合指数为ix_table_1__table_2__table_3(table1, table2, table_3)
如果这样做 - 为什么,如果不这样做 - 为什么?
(我不同意另一个答案中推荐的索引。)
SELECT * FROM tt
JOIN table1 t1 ON tt.table_1 = t1.id
JOIN table2 t2 ON tt.table_2 = t2.id
JOIN table3 t3 ON tt.table_3 = t3.id
WHERE t2.value = 'test'
Run Code Online (Sandbox Code Playgroud)
当优化器选择如何执行 a 时JOIN,它通常会这样工作:
WHERE。这将是t2。所以需要以INDEX 开头value。tt,因为ON这次有条款。t1和t3,按任一顺序。现在按上面的顺序列出索引:
t2: INDEX(value)
tt: INDEX(table_2)
Run Code Online (Sandbox Code Playgroud)
t1并t3通过他们的id. id所以,假设你遵循成为 PK的惯例,那么PRIMARY KEY(id)就已经存在了。
现在让我们切换到新版本的查询:
SELECT t1.foo1, t2.foo2, t3.foo3 FROM tt ...
Run Code Online (Sandbox Code Playgroud)
这样,我们就可以制作更好的索引。“覆盖”索引是INDEX包含查询中任何位置所需的所有列的索引。因此,让我们添加任何此类列:
t2: INDEX(value, id, foo2)
tt: INDEX(table_2, table_3, table_1) -- table_2 must be first
Run Code Online (Sandbox Code Playgroud)
考虑“覆盖”索引时需要注意两件事:
PRIMARY KEY,创建“覆盖”索引没有任何优势。PK 与数据“聚集”,因此有效地“覆盖”。*) 列。有关创建最佳索引的更多信息:http://mysql.rjweb.org/doc.php/index_cookbook_mysql
唉,EXPLAIN显示了用可用的东西做了什么;它没有说明应该添加什么索引,也没有其他提示。
您的表格看起来不像传统的“many:many”表格。有关该类型表的具体提示,请参阅: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
FOREIGN KEYs:FK 提供 (1) 约束(用于数据完整性)和 (2) 使INDEX检查该约束变得高效。当您同时创建 FK和时INDEX,MySQL可能会足够聪明,在仅需要 2 个索引的情况下避免使用 2 个索引。 INDEX(table_2)是 FK 所需要的一切,但INDEX(table_2, table_3, table_1)会为该 FK“工作”。拥有这两个索引是一种浪费;如果不需要添加较短的,请将其删除。