【发布时间】:2017-09-08 16:47:07
【问题描述】:
背景
这个问题是previous question 的后续问题。在这里也为您提供上下文,我想总结上一个问题:在我上一个问题中,我打算有一种方法来执行选择而不将其结果发送给客户。目标是在不消耗大量资源的情况下通过发送数百万数据来衡量性能。我只对执行这些查询所需的时间感兴趣,而不是它们将结果发送到客户端应用程序的时间,因为我打算优化查询,所以查询的结果根本不会改变,但方法会改变,我打算能够比较这些方法。
当前知识
在我的另一个问题中,提出了几个想法。一个想法是选择记录的数量并将其放入变量中。但是,这显着改变了查询计划,并且结果在性能方面并不准确。也提出了使用临时表的想法,但是如果我们不知道要测量的输入是什么查询并且还会引入大量白噪声,那么创建一个临时表并将其插入是很困难的,因此,即使这个想法很有创意,它不适合我的问题。最后,Vladimir Baranov 提出了一个想法,即创建与选择返回的列一样多的变量。这是一个好主意,但我通过创建一个 nvarchar(max) 变量并将我的所有列选择到其中来进一步改进它。这个想法很有效,除了一些问题。我有大部分问题的解决方案,但我想分享它们,所以,我无论如何都会描述它们,但不要误解我,我有一个问题。
问题1
如果我有一个@container 变量并且我在每个选择中都做了一个@container = columnname,那么我就会遇到转换问题。
解决方案1
我需要做一个@container = cast(columnname as nvarchar(max)),而不是仅仅做一个@container = columnname
问题2
对于选择中的每一列,我需要将<whatever> as something 转换为@container = cast(<whatever> as nvarchar(max)),但对于子选择,我需要一个通用的解决方案来处理case when 和括号,我不想有任何实例@container = 的任意位置,主选区左侧除外。
解决方案2
由于我对正则表达式一无所知,我可以通过迭代查询字符串来解决这个问题,直到我找到主查询的from,每次我找到一个括号,我什么都不做,直到那个括号关闭,找到应该放置@container = 和应该取出as [customname] 的索引,并在查询字符串中从右到左执行所有这些操作。这将是一个冗长而不优雅的代码。
问题
是否可以确保我的所有主要列都以@container = 开头,而以as [Customname] 结尾?
【问题讨论】:
-
为确保执行计划不会改变,请考虑使用丢弃查询结果选项从 SSMS 或使用 ExecuteNonQuery 从 Powershell 执行数据库服务器上的 proc。尽管 SQL Server 仍会返回结果,但只会考虑 API 处理时间(不考虑网络、呈现或其他处理)。
-
@DanGuzman 如果我有 \@container = foo 而不是 foo 作为 [bar],查询计划是否可能更改?
-
如果源和目标的数据类型不完全匹配,则需要进行转换(显式或隐式),这会影响性能。我不能说我遇到了具有匹配类型的不同计划的情况,但是当返回多行时,我很少使用 SELECT 进行变量赋值,由于行为未定义,它可能不适用于所有情况,或者行为可能会因 SQL 版本等而改变。这样做需要您自担风险。
-
@DanGuzman 如果我理解正确,您是说由于变量分配和转换,测量可能不准确,您建议执行 ExecuteNonQuery。我需要在 SQL Server 级别计算性能以及从那里返回的值。如果我调用 ExecuteNonQuery,那么我将需要在 Powershell 级别或应用程序级别进行测量。
-
你是对的 - 我建议你在客户端 API 级别测量时间(没有客户端渲染/处理时间)。我知道你在问什么,但我认为这不可能可靠地完成。此外,考虑时间应该包括数据库引擎为填充 TDS 协议结果缓冲区所做的工作,这是从应用代码调用时将发生的事情的一部分。
标签: sql-server vb.net