sql-server – 搜查是否存在EXISTS优于COUNT! ……不是吗?
表现EXISTS测试的输入树的一部门如下所示: ScaOp_Exists LogOp_Project LogOp_Select LogOp_Get TBL: #T2 ScaOp_Comp x_cmpEq ScaOp_Identifier [T2].ID ScaOp_Identifier [T1].ID 这由RemoveSubqInPrj转换为以下布局: LogOp_Apply (x_jtLeftSemi probe PROBE:COL: Expr1008) 这是左半连策应用前面描写的探针.此初始转换是迄今为止SQL Server查询优化器中独一可用的转换,假如禁用此转换,编译将失败. 此查询的也许执行打算外形之一是该逻辑布局的直接实现: 最终的Compute Scalar行使探测列值评估CASE表达式的功效: 当优化思量半毗连的其他物理毗连范例时,将保存打算树的根基外形.只有归并毗连支持探测列,因此不思量逻辑上也许的散列半毗连: 请留意,归并输出一个标志为Expr1008的表达式(名称与之前的名称沟通是偶合),但打算中的任何运算符都没有界说.这只是探测列.和早年一样,最终的Compute Scalar行使此探测值来评估CASE. 题目是优化器没有完全试探只有归并(或散列)半毗连才有效的更换方案.在嵌套轮回打算中,搜查T2中的行是否与每次迭代的范畴匹配没有任何甜头.行使归并或哈希打算,这也许是一个有效的优化. 假如我们在查询中向T2添加匹配的BETWEEN谓词,那么全部产生的工作都是对每一行执行此搜查作为归并半毗连上的残差(很难在执行打算中找到,但它就在哪里): SELECT T1.ID,CASE WHEN EXISTS ( SELECT 1 FROM #T2 AS T2 WHERE T2.ID = T1.ID AND T2.ID BETWEEN 5000 AND 7000 -- New ) THEN 1 ELSE 0 END AS DoesExist FROM #T1 AS T1 WHERE T1.ID BETWEEN 5000 AND 7000; 我们但愿BETWEEN谓词会被推迟到T2导致搜刮.凡是,优化器会思量这样做(纵然查询中没有特另外谓词).它辨认隐含的谓词(T1上的BETWEEN和T1和T2之间的毗连谓词一路体现T2上的BETWEEN),而原始查询文本中不存在它们.不幸的是,apply-probe模式意味着没有试探. 有一些要领可以编写查询以在归并半毗连的两个输入上发生搜刮.一种要领是以很是不天然的方法编写查询(打败我凡是更喜好EXISTS的缘故起因): WITH T2 AS ( SELECT TOP (9223372036854775807) * FROM #T2 AS T2 WHERE ID BETWEEN 5000 AND 7000 ) SELECT T1.ID,DoesExist = CASE WHEN EXISTS ( SELECT * FROM T2 WHERE T2.ID = T1.ID ) THEN 1 ELSE 0 END FROM #T1 AS T1 WHERE T1.ID BETWEEN 5000 AND 7000; 我不满足在出产情形中编写该查询,只是为了证明所需的打算外形是也许的.假如您必要编写的真实查询以这种特定方法行使CASE,而且机能受到归并半毗连的探测端没有搜刮的影响,您可以思量行使发生正确功效的差异语法编写查询更有用的执行打算. (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |