我继承的代码中有以下查询:
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);
创建索引后,我将手动描述性地重命名每个索引。是否可以在命令中包含索引的名称?
非常感谢!
最佳答案
这是您的查询:
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
索引,但没有什么区别。另外,您将列命名为“行”确实很奇怪 - 对我来说,这会导致认知失调。
实际上,除非您的查询中有拼写错误,否则您可以省略 table3
然后就这样做:
WHERE b.row2 IN ($table3_ids)
请注意in ($table3_ids)
需要字符串替换。这不能参数化。这引入了 SQL 注入(inject)的危险。
如果您的结果集超过几百行,也许几千行,那么order by
将具有重要意义。如果是这种情况,您可能需要尝试不同的方法来获得您想要的结果。
关于php - 使用随机组件优化和索引查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31600529/