【问题标题】:Sql Server Query OptimizationSql Server 查询优化
【发布时间】:2010-06-23 20:07:14
【问题描述】:

我想在具有许多过滤器的存储过程中编写查询,但我想避免使用动态 SQL。

假设我的参数可以为空(@filter1、@filter2、@filter3...)。我可能解决这个问题的一种方法是:

SELECT col1, col2, col3
FROM table
WHERE col1 = ISNULL(@filter1, col1)
AND col2 = ISNULL(@filter2, col2)
AND col3 = ISNULL(@filter3, col3)

如果不为空,则此结果将由适当的过滤器过滤。问题是: 1)这是一种好习惯吗? 2) 优化器会优化 col1 = col1 还是会影响查询性能?

【问题讨论】:

  • 性能会很糟糕,因为有太多可能的组合,查询计划不太可能被缓存。动态 SQL 是一个更好的选择。
  • Erland Sommarskog 将an excellent article 放在一起解决此类问题。我强烈建议您通读一遍。

标签: sql sql-server query-optimization


【解决方案1】:

关于优化条件:您必须意识到编译计划必须满足任何变量值。因此,当生成计划时,SQL Server 必须创建一个访问计划,该计划在@filter1 为 NULL 时有效,并且在@filter1 不为 NULL 时也有效。结果几乎总是扫描。

Tom H. 链接的文章对此进行了详细介绍。

【讨论】:

    【解决方案2】:

    ISNULL 可能会损害索引的使用,所以我不会说它是理想的,但如果您需要上述功能,我不确定是否有解决方法。

    您能否查看您的执行计划以查看您希望使用的索引是否正在使用?

    【讨论】:

    • 这种结构通常可以正常工作。 COALESCE 可能是杀手,因为它处理数据类型的方式
    • 有趣,ISNULL 与 COALESCE 有什么推荐的读数吗?
    【解决方案3】:

    1) 这是一种好的做法吗? 2) 优化器会优化 col1 = col1 还是会影响查询性能?

    是的,这是一个很好的做法。

    有些 RDBMS 会优化它,有些则不会。如果您将其称为准备好的语句,则不会。

    不要过早优化;在大多数情况下,成本差异可能可以忽略不计,或者如果不是,可以通过适当的指数忽略不计。

    专注于编写清楚地表达您正在做的事情的代码。在我看来,这个成语简洁明了。

    【讨论】:

    • 我非常支持不要过早地进行优化,但在这种情况下,性能影响通常会很大,而且索引不太可能有帮助,因为查询每次都可能做不同的事情。这种类型的功能通常是系统范围的(即您需要对许多不同的表进行动态搜索),因此最好在编写 50 个 SP 之前了解您的一般方法,然后您必须重写。
    • 这不是为时过早的优化,它是为性能而设计的,应该在每个数据库上完成。当技术之间的性能存在已知差异时,应从一开始就选择性能最佳的技术。众所周知,Databasea 难以重构。当性能成为问题时,为时已晚。过早的优化并不意味着没有优化。
    【解决方案4】:

    如果您希望此表增长到任何可观的大小,这不是一个好主意,因为查询优化器不会缓存执行计划,并且优化器在处理此类情况时很糟糕,因为它可以'在编译时不容易知道执行路径是什么。

    您最好只在客户端生成一个查询,并在 where 子句中使用正确的过滤器,而不是尝试编写一个包罗万象的查询。

    【讨论】:

      【解决方案5】:

      根据我的经验(通过在大型表上运行一些基准测试):

      (col1 = @filter or @filter IS NULL)
      

      比:

      col1 = ISNULL(@filter1, col1)
      

      【讨论】:

        猜你喜欢
        • 2013-08-11
        • 1970-01-01
        • 2014-11-04
        • 2013-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多