【问题标题】:SQL Server Where Clause PerformanceSQL Server Where 子句性能
【发布时间】:2019-02-12 11:26:35
【问题描述】:

我有一个 SQL 查询,它查看 where 子句中的 10 多个条件。我不确定下面哪种方式在性能方面会更好。我的一些参数很重要,有些参数是次要的。

如果您能解释哪个更好以及为什么我将不胜感激。

我的参数

DECLARE @ParamImportant1 int, @ParamImportant2 int, @ParamImportant2 int,
@ParamSecondary1 int, @ParamSecondary2 int,@ParamSecondary3 int

第一种方法 我有一个包含所有参数的索引。

SELECT 
* 
FROM MyTable
WHERE Col1 = @ParamImportant1 AND Col2 = @ParamImportant2 AND Col3 = @ParamImportant3
AND (@ParamSecondary1 IS NULL OR ColSec1 = @ParamSecondary1)
AND (@ParamSecondary2 IS NULL OR ColSec2 = @ParamSecondary2)
AND (@ParamSecondary3 IS NULL OR ColSec3 = @ParamSecondary3)

第二种方法 使用子查询或 cte 划分查询。

SELECT
*
FROM
(
   SELECT 
   * 
   FROM MyTable
   WHERE Col1 = @ParamImportant1 AND Col2 = @ParamImportant2 AND Col3 = @ParamImportant3
) X
WHERE (@ParamSecondary1 IS NULL OR ColSec1 = @ParamSecondary1)
AND (@ParamSecondary2 IS NULL OR ColSec2 = @ParamSecondary2)
AND (@ParamSecondary3 IS NULL OR ColSec3 = @ParamSecondary3)

第三种方法 使用临时表

 SELECT 
 * 
 INTO #MyTemp
 FROM MyTable
 WHERE Col1 = @ParamImportant1 AND Col2 = @ParamImportant2 AND Col3 = @ParamImportant3

SELECT
*
FROM #MyTemp
WHERE (@ParamSecondary1 IS NULL OR ColSec1 = @ParamSecondary1)
AND (@ParamSecondary2 IS NULL OR ColSec2 = @ParamSecondary2)
AND (@ParamSecondary3 IS NULL OR ColSec3 = @ParamSecondary3)

【问题讨论】:

  • 你真的打算在这里使用SELECT *吗?通过选择 Col1Col2Col3 以外的列,SQL Server 可能会选择不使用您定义的索引。
  • 您是否使用过 SQL 解释方法来展示它的作用?还是分析器?
  • 这取决于您的数据结构,没有明确的答案。一般来说:检查统计数据并解释每个案例的数据计划(我总是从读取次数开始)
  • 这看起来也是一个包罗万象的查询。我建议使用OPTION (RECOMPILE),否则(如果这是一个存储过程)缓存的查询计划不太可能对每次调用 SP 都有用。
  • 我建议是,@MehmetOtkun。在 (Revisiting) Catch-all Queries 上阅读 Gail 的文章。你会注意到她在这里讨论的确切类型的查询就是你的风格。

标签: sql sql-server tsql


【解决方案1】:

在大多数情况下,您的第一个版本应该可以正常工作:

WHERE Col1 = @ParamImportant1 AND
      Col2 = @ParamImportant2 AND
      Col3 = @ParamImportant3 AND
      (@ParamSecondary1 IS NULL OR ColSec1 = @ParamSecondary1) AND
     (@ParamSecondary2 IS NULL OR ColSec2 = @ParamSecondary2) AND
     (@ParamSecondary3 IS NULL OR ColSec3 = @ParamSecondary3)

您想要的索引需要以三个重要列开头。然后它也可以包含其他列(col1, col2, col3, colsec1, colsec2, colsec3)

请注意,索引将通过col1, col2, col3 的所有值进行扫描。也就是说,索引不会减少辅助列的行数。

在大多数情况下,这似乎是合理的。如果不是这样,那么您可能需要多个索引和动态 SQL。

【讨论】:

    【解决方案2】:

    避免参数中的“智能逻辑”,否则 MSSQL 无法找出获取数据的最佳方式。

    获得最佳执行计划最可靠的方法是避免 SQL 语句中不必要的过滤器。

    https://use-the-index-luke.com/sql/where-clause/obfuscation/smart-logic

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      • 2017-05-27
      • 2017-02-26
      • 2018-11-08
      • 1970-01-01
      相关资源
      最近更新 更多