在 "ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'" 上询问原因?
Ask reason on "ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'"?
我知道这个限制和重写的替代方法SQL。但我想知道为什么?任何人都可以提供有关此限制的推论吗?
类似
的查询
select * from table where id in (select id from othertable)
基本上会被解释为
select * from table where exists
(select id from othertable where table.id = othertable.id)
这就是您对该查询的期望。您特别希望 IN
查询使用 othertable.id
上的索引。在manual中描述为
Some optimizations that MySQL itself makes are: [...]
- MySQL rewrites IN, ALL, ANY, and SOME subqueries in an attempt to take advantage of the possibility that the select-list columns in the subquery are indexed.
如果您添加 limit
:
,这并非纯属巧合,正是错误消息中提到的四个运算符
select * from table where id in
(select id from othertable order by id limit 10)
ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'.
不再可以直接以类似方式重写该查询,因为它不同于
select * from table where exists
(select id from othertable where table.id = othertable.id
order by id limit 10)
要执行带有限制的 IN
,MySQL 可以检索 othertable
的前 10 行,将该结果集存储为 派生子 table 并检查 id 是否在其中。你当然可以这样做:
select * from table where id in
(select id from
(select id from othertable order by id limit 10) subtable)
类似于第一个示例,这将被解释为
select * from table where exists
(select * from
(select id from othertable order by id limit 10) subtable
where table.id = subtable.id)
所以它混合了优化器的工作方式(它将重写查询)、limit
的工作方式(它在 找到 行后停止执行,而不是跳过它们)、期望的内容(索引的使用)以及开发人员最终是否决定允许特定语法。
您可能会争辩说,如果 MySQL 遇到带有 limit
子查询的 IN
,它总是可以回退以作为派生 table 执行查询 - 但也可以你通过明确地使用派生的 subtable。您还可以争辩说您可以想办法实现它或以不同的方式实现它 - 你是对的,确实有。这就是错误消息中出现“yet”的原因。因此,请随意实施它们或至少描述它们,例如在功能请求中尽可能彻底地考虑 MySQL 的所有其他部分如何工作。但要确保它们实际上比仅使用 subtable.
更快
我知道这个限制和重写的替代方法SQL。但我想知道为什么?任何人都可以提供有关此限制的推论吗?
类似
的查询select * from table where id in (select id from othertable)
基本上会被解释为
select * from table where exists
(select id from othertable where table.id = othertable.id)
这就是您对该查询的期望。您特别希望 IN
查询使用 othertable.id
上的索引。在manual中描述为
Some optimizations that MySQL itself makes are: [...]
- MySQL rewrites IN, ALL, ANY, and SOME subqueries in an attempt to take advantage of the possibility that the select-list columns in the subquery are indexed.
如果您添加 limit
:
select * from table where id in
(select id from othertable order by id limit 10)
ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'.
不再可以直接以类似方式重写该查询,因为它不同于
select * from table where exists
(select id from othertable where table.id = othertable.id
order by id limit 10)
要执行带有限制的 IN
,MySQL 可以检索 othertable
的前 10 行,将该结果集存储为 派生子 table 并检查 id 是否在其中。你当然可以这样做:
select * from table where id in
(select id from
(select id from othertable order by id limit 10) subtable)
类似于第一个示例,这将被解释为
select * from table where exists
(select * from
(select id from othertable order by id limit 10) subtable
where table.id = subtable.id)
所以它混合了优化器的工作方式(它将重写查询)、limit
的工作方式(它在 找到 行后停止执行,而不是跳过它们)、期望的内容(索引的使用)以及开发人员最终是否决定允许特定语法。
您可能会争辩说,如果 MySQL 遇到带有 limit
子查询的 IN
,它总是可以回退以作为派生 table 执行查询 - 但也可以你通过明确地使用派生的 subtable。您还可以争辩说您可以想办法实现它或以不同的方式实现它 - 你是对的,确实有。这就是错误消息中出现“yet”的原因。因此,请随意实施它们或至少描述它们,例如在功能请求中尽可能彻底地考虑 MySQL 的所有其他部分如何工作。但要确保它们实际上比仅使用 subtable.