选项(OPTIMIZE FOR(@ AccountID = 148))

时间:2017-06-19 18:57:27

标签: sql-server

我最近在一个大型,复杂的生产查询中看到了这个语句,每分钟执行几百次。此查询的原始作者似乎试图在AccountId = 148时优化查询。表中可能出现总共811个不同的帐户ID值。值148表示此表中所有行的9.5%(总计约60.1M行)并且具有任何帐户值的最高总数

我从来没有遇到过这样的人。在我看来,只有当@AccountId参数等于148时,它才具有重要价值。否则,查询计划可能会假设返回的行数比实际更多。在这种情况下,可能会执行扫描而不是搜索。

那么,在这种情况下,这样做有什么实际价值吗?

1 个答案:

答案 0 :(得分:3)

假设帐户148覆盖表格的10%,而其他所有帐户仅占0.001%的极端情况。好吧,鉴于该帐户代表了您数据的10%,因此也可以比其他帐户更频繁地搜索它。现在想象一下,对于任何其他帐户,在少量行上的嵌套循环连接将非常快,但对于帐户148,它将非常慢并且散列连接将是最佳选择。

进一步想象一下,运气不好,在重启/计划回收后进入系统的第一个查询是一个帐户其他而不是148。你现在被困在一个计划在10%的时间内表现极差,即使它对其他数据也非常有用。在这种情况下,您可能希望优化器在10%的时间内坚持不是灾难的计划,即使这意味着它略微低于其他时间的最佳状态。这是OPTIMIZE FOR的用武之地。

备选方案是OPTIMIZE FOR UNKNOWN(如果您的分发更加均衡,但您需要防止意外计划锁定来自不具代表性的参数),RECOMPILE(这可能对性能产生相当大的影响)经常执行的查询),显式提示(FORCESEEKOPTION HASH JOIN等),添加细粒度自定义统计信息(CREATE STATISTICS)和拆分查询(IF @AccountID = 148 ...),可能组合使用使用过滤索引。但除了所有这些,OPTIMIZE FOR @Param = <specific non-representative value>肯定有一席之地。