进一步研究this question我在High Peformance MySQL一书中找到了以下内容(第219页):
... MySQL对IN列表中的值进行排序并使用快速二进制文件 搜索以查看值是否在列表中。
它认为这种方法是最优的,在列表大小中测量为O(logN)
,并且这是一种非常好的方法(而不是转换为一系列OR
语句)。
但似乎忽略了列表的排序为O(NlogN)
,因此结果比执行一系列OR
O(N)
更糟糕。
我在这里误会了什么?
为了清楚起见,这个目标是列表是来自另一个SELECT
答案 0 :(得分:5)
首先,对于带有子查询的in
,这种说法是不正确的。为此,要么为数据中的每一行(前5.6 MySQL)运行子查询,要么使用连接优化。
其次,在使用列表计算in
的顺序时会发生两件事。你的两个陈述中隐含的是“每一行都在进行”。因此,如果正在处理R行,则实际语句为O(R * logN)
与O(R*N)
,其中N
是列表的大小。
排序列表的创建发生在编译时,发生一次。因此,订单声明为O((R * logN) + N * logN))
。我相信这个假设是R
>> N
,因此它在表达中占主导地位。换句话说,因为排序发生一次并且每行都在查看算法,所以编译工作就会消失。