【问题标题】:How to optimize a T-SQL query that fetches from one or the other of two tables如何优化从两个表中的一个或另一个中获取的 T-SQL 查询
【发布时间】:2020-02-27 00:54:28
【问题描述】:

有两个相同的表。动态参数将确定从两个表中的哪一个获取数据。我采用的方法是合并两个表的结果,并为每个子查询添加一个谓词以过滤传入的参数(请参见下文)。这产生了一个估计的执行计划,该计划读取两个表,然后应用过滤器。有没有办法在不使用条件(如 IF)的情况下优化查询,以便只查询适当的表?

create table Flip (ID uniqueidentifier)
create table Flop (ID uniqueidentifier)

查询

declare @useFlip bit
select * from Flip where @useFlip=1
union
select * from Flop where @useFlip<>1

执行计划

【问题讨论】:

  • 顺便说一句,union all 而不是 union 大概可以删除 63% 的排序步骤
  • 从答案中的 cmets 看来,我们这里没有完整的图片(因为您现在告诉我您正在使用 iTVF,您没有在上面详细说明) .似乎我们需要被告知您要解决的真正问题,否则如果使用 UNION ALL 无济于事,这可能是一个 XY 问题。
  • 如果函数是内联的并且结果查询具有recompile 查询提示,那么查询优化器应该做正确的事℠。不幸的是,iTVF 无法强制使用查询重新编译。

标签: tsql query-optimization sql-server-2014


【解决方案1】:

我个人会转向动态声明或IF...ELSE 逻辑。由于您只会查询一个表,因此创建一个相关的计划更有意义。

动态方法:

DECLARE @SQL nvarchar(MAX);

SET @SQL = N'SELECT * FROM ' + QUOTENAME(CASE @UseFlip WHEN 1 THEN N'Flip' ELSE N'Flop' END) + N';';
EXEC sp_executesql @SQL;

IF...ELSE方法:

IF @UseFlip = 1
    SELECT * FROM Flip;
ELSE
    SELECT * FROM Flop;

编辑: 上述内容已完全无效,因为 OP 在此答案下方发表评论,建议他们使用内联表值函数(此时此信息不在问题中)。这些语句都不能在 iTVF 中使用。

【讨论】:

  • 嗯,我试图避免使用 IF...ELSE,因为我喜欢将查询作为内联表值函数的一部分。
  • 你为什么没有在@Sumith 的问题中提到这一点?这完全使我的答案无效......
  • 问题中有。我说我想避免条件(如 IF)。
  • “我不想使用 IF 不会转换为“我正在使用 iTVF,因此所有内容都必须在一个语句中。” @Sumith。
  • 但我不想使用 IF...ELSE。此外,当我第一次输入问题时,它有创建函数定义,这似乎是一个很大的问题。因此,我将其缩减为特定的位。现在,关于这个主题,是否有不同的方式来表达查询的语义,以便不扫描两个表?或者有没有办法让 SQL 在 @useFilp=1 时使用一个计划,而在 @useFlip=0 时使用另一个计划?
猜你喜欢
  • 1970-01-01
  • 2021-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 2013-05-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多