【问题标题】:Performance Issue due to GOTO statement由于 GOTO 语句导致的性能问题
【发布时间】:2020-06-27 10:03:22
【问题描述】:

我正在使用 SQL Server 2016 数据库项目,我的脚本如下所示

DECLARE Marker NVARCHAR(50) = (SELECT Value FROM Table1 WHERE name = 'Marker') 
IF( IS NOT NULL)
BEGIN
    IF @Marker = 'Marker1' GOTO Marker2;
    IF @Marker = 'Marker2' GOTO Marker3;
    IF @Marker = 'Marker3' GOTO Marker4;
    IF @Marker = 'Marker4' GOTO Marker5;
    IF @Marker = 'Marker5' GOTO Marker6;
    IF @Marker = 'Marker6' GOTO Marker7;        
    ELSE GOTO EmptyBlock;    
END 

MARKER1:
Code for marker 1

MARKER2:
Code for marker 2    

MARKER3:
Code for marker 3
.
.
.
EmptyBlock:
PRINT 'No changes'

此脚本文件将在每次部署后执行,并且根据部署,它将跳过前面的行,现在将到达 ma​​rker 15

虽然代码行数不多,但执行起来却花费了太多时间,由于GOTO语句,我终于找到了问题所在。我不知道使用 GOTO 是否是最佳做法,如果在生产现场使用它不是很好的做法,那么请给我一些 GOTO 替代品的建议。

【问题讨论】:

  • 您怎么知道goto 语句是问题所在? goto 本身似乎不太可能导致问题,更有可能是在给定分支下运行的代码。
  • 我已经通过删除 goto 语句手动执行它,然后它将执行更少的时间,goto 本身似乎不太可能导致问题 => 不知道它是否会导致问题与否,因为到目前为止它在部署时可以正常工作,但需要时间并且会随着标记一起增加:(
  • 最好的办法是检查(然后发布)执行计划。
  • 你在问题​​中写的方式,如果代码跳转到MARKER,那么它也会执行MARKER2MARKER2等等。你的代码真的是这样吗?
  • 您显示的代码中没有任何内容会导致性能问题。一般情况下,GOTO 会很快,它并不像它必须做任何事情。所以导致性能问题的原因与整个代码有关,因此我们需要查看执行计划(这是任何性能问题的重要组成部分)。

标签: sql-server database-project


【解决方案1】:

您可以使用IFGOTO 语句替换为这样的脚本:

-- get the number of the marker (instead of the full name of the marker).
DECLARE @Marker INT = (SELECT REPLACE(Value, 'Marker', '') FROM Table1 WHERE name = 'Marker')

IF @Marker IS NULL
  BEGIN
    PRINT 'no marker'
  END
IF @Marker < 1
  BEGIN
    -- Code for Marker No. 1
  END
IF @Marker < 2
  BEGIN
    -- Code for Marker No. 2
  END
IF @Marker < 3
  BEGIN
    -- Code for Marker No. 3
  END
IF @Marker < 4
  BEGIN
    -- Code for Marker No. 4
  END
ELSE IF @Marker IS NOT NULL
  BEGIN
    PRINT 'no changes'
  END

demo on dbfiddle.uk

【讨论】:

  • 您遗漏了一堆 ELSE 语句。如果您认为这是操作的意图,则应在答案中注明。
猜你喜欢
  • 2011-12-03
  • 1970-01-01
  • 2013-04-04
  • 2021-08-09
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2013-04-01
  • 2011-08-08
相关资源
最近更新 更多