3. 什么是动态计划?
动态计划可以增量地进行,在SQL Server中,我们通过将查询执行状态序列化到maker中来实现。然后,我们可以构建一个新的查询计划树,使用刚刚的maker来复位每个操作。另外,动态计划可以根据当前位置前后移动。dynamic和一些fast_forward游标都会使用动态计划。
动态计划只包括动态运算符(支持maker及前后的移动),这很像流操作符中进行查询的notion(stop-and-go)。但并不是每个流操作符都是动态的。
在SQL Server中,动态意味着:
(1) 操作符可以使用maker复位到它当前的位置,或者到当前位置的相关位置(下一个或前一个)
(2) 操作符状态一定要小,从而使maker比较小。操作符中不能存储行数据,尤其是sort table、hash table或者work table,甚至一行都不可以,因为即使单行也可能很大。
没有动态计划,游标可能需要临时存储媒介来保存查询结果集(或它的keyset)。然而,某些操作符对动态执行计划来说是不合适的,比如hash join、hash agg、compute sequence和sort。这会导致一个次优的计划。
4. 什么时候动态计划会不如静态计划?
在某些查询中,比如使用row_number的,动态计划是不可用的。但是当动态静态都可用时就有问题出现了:在某个操作符(比如join)既有动态(nested loops)也有非动态(hash)实现时可能发生;当有些索引支持排序而有些不支持时,也可能会发生问题。
下面是一个例子,表ORDERS有一个DATE上的索引,以及一个SUBTOTAL上的索引(在这个例子中,clustered或者non-clustered没关系)。该查询想要查询订单信息:
SELECTDATE, SUBTOTAL, ORDERID, CUSTOMERID
FROM ORDERS where SUBTOTAL > 10000000
ORDERBYDATE
表中有一亿条数据,查询结果包含100条。动态游标不能排序,所以它必须使用DATE索引,查看每条数据,填到SUBTOTAL中。而静态游标可以查询大于10000范围的SUBTOTAL索引,排序并把它们存储到游标(temp table)中。
5. fast_forward游标如何解决该问题?
在特定条件下,fast_forward游标从非常好的静态计划和非常好的动态计划中选择开销最小的一个。在上面所提到的极端例子中,它就会使用静态计划。
6. 应用开发者可以做什么?
(1) 为OPTION(FAST )选择一个中性值。
(2) 通过调用sp_cursorprepare或OPTION(RECOMPILE)避免在不同参数下的计划重用。
(3) 避免在游标中使用ORDER BY
(4) 使用相等谓词及多列索引来支持序列。稍微修改一下上面的例子,如果我们在SUBTOTAL范围有一个包含值{S,M,L,XL}的计算列SIZE,我们可以查询WHERE SIZE=’XL’ ORDER BY DATE,并在上使用索引。通常通过增加索引列来包括相等谓词后的排序列。