我想知道从 Oracle 子查询返回的值是否丢失索引。
select * from emp where empid = 1
-- empid is indexed
select t1.* from (select t2.* from emp t2) t1 where t1.empid = 1
-- t1.empid is still indexed?
是的,第二个查询使用索引。事实上,两者都编译成完全相同的执行计划。检查它SQLFiddle。
您应该记住 SQL 处理是惰性的:子查询不一定完全执行以获取顶级查询的输入数据。相反,它们应该被视为可以根据需要调用以获取该数据的代码。
查询优化过程的一部分是简化所提供查询的结构。这通常意味着用连接替换 IN 和 EXISTS,将谓词推入内联视图并完全消除子查询。
事实上,由于这种行为非常普遍,因此有一些技术(例如优化器提示、公用表表达式或某些逻辑冗余子句)专门用于防止谓词推送和子查询合并以及其他无意中不利的查询转换。
默认情况下,您应该期望子查询和内联视图将在逻辑上可能的情况下合并到父查询中,正如其他人所提到的,在您的示例中几乎肯定是这种情况。
当然,从所有这些来看,使用子查询或内联视图通常不会削弱优化器使用索引或查询重写或各种其他性能增强技术的能力。
这个问题没有简单的答案:有时是,有时不是。这取决于许多因素。一般来说,只是不要深入理论,尽量避免这种查询写作风格是安全的,或者换句话说,在大多数情况下,观点都是不好的。有关详细信息,请参阅http://www.orafaq.com/tuningguide/push%20predicates.html 。