我在继承的代码中有以下查询:
SELECT a.row2, a.row3
FROM table1 a
JOIN table2 b ON a.row1 = b.row1
WHERE b.row2 IN (
SELECT id
FROM table3
WHERE id IN ($table3_ids)
)
ORDER BY RAND();
[a.row1是table1的主键]
几个问题:
是否有更有效的方法来构建此查询?
我已经在table1上有一个索引(row1,row2,row4);为(row1,row2,row3)创建一个单独的索引是多余的,或者我应该用(row1,row2,row3,row4)上的索引替换前者?
从另一端,我已经在table2上有一个索引(row1,row2,row3);因为看起来我需要table2中的索引(row1,row2)来优化这个查询,所以包含一个索引是多余的,只需从同一个表中的不同索引中排除单个元素
这是我不清楚查询引擎如何知道哪个索引合适的地方;当它解析查询时,它是否首先检查表中的匹配索引?
最后(也许最简单的回答),我正在用这种语法添加索引:
ALTER TABLE table_name ADD KEY(row1,row2,row3);
创建索引后,我会手动重命名每个索引。是否可以在命令中包含索引的名称?
非常感谢!
答案 0 :(得分:1)
这是您的查询:
SELECT a.row2, a.row3
FROM table1 a JOIN
table2 b
ON a.row1 = b.row1
WHERE b.row2 IN (SELECT id FROM table3 WHERE id IN ($table3_ids))
ORDER BY RAND();
我认为最好的索引是:table2(row2, row1)
和table1(row1, row2, row3)
以及table3(id)
。您可以将row4
添加到table1
索引,但它并没有什么不同。另外,你把你的专栏命名为#34; row"真的很奇怪。 - 对我来说,这会导致认知失调。
实际上,除非您的查询中有拼写错误,否则您可以省略table3
并执行以下操作:
WHERE b.row2 IN ($table3_ids)
请注意,in ($table3_ids)
需要字符串替换。这不能参数化。这引入了SQL注入的危险。
如果你的结果集超过几百行,可能是几千行,那么order by
将是重要的。如果是这种情况,您可能希望尝试不同的方法来获得所需的结果。
答案 1 :(得分:1)
Gordon回答的一些补充:
ALTER TABLE reference在语法中显示可选的index_name
。
IN ( SELECT ... )
非常低效;把它变成JOIN
:
SELECT a.row2, a.row3
FROM table1 a
JOIN table2 b ON a.row1 = b.row1
JOIN table3 c ON b.row2 = c.id
WHERE c.id IN ($table3_ids) )
ORDER BY RAND();
...或
SELECT a.row2, a.row3
FROM table1 a
JOIN table2 b ON a.row1 = b.row1
WHERE b.row2 IN ($table3_ids) )
ORDER BY RAND();
(需要c
的可能原因:您正在过滤c
中缺少的ID?)
ORDER BY RAND()
代价高昂。除非您还有LIMIT
。