标签: query-performance

无重复组合的 SQL 查询

我需要一个可以在(或作为)函数中使用并检索 n 值的所有组合的查询。我需要长度 k 的所有组合,其中 k = 1..n。

扩展样本输入和结果,因此输入有 3 个值而不是 2 - 但是,输入值的数量可能从 1 到 n 不等。

示例:输入:在多行中的一列中包含值的表

Value  (nvarchar(500))
------
Ann
John
Mark
Run Code Online (Sandbox Code Playgroud)

输出#1:在一列中连接值的表

    Ann
    John
    Mark
    Ann,John
    John,Mark
    Ann,Mark
    Ann,John,Mark
Run Code Online (Sandbox Code Playgroud)

performance sql-server query-performance

22
推荐指数
1
解决办法
3万
查看次数

操作员使用 tempdb 在溢出级别 2 的执行期间溢出数据

我正在努力通过警告Operator usedtempdb最大限度地减少查询计划的排序操作成本to spill data during execution with spill level 2

在溢出级别 1 的执行期间发现了几篇与溢出数据相关的帖子,但不是级别 2。级别 1 似乎是由过时的统计数据引起的,那么级别 2 呢?我找不到任何与level 2.

我发现这篇与排序警告相关的文章非常有趣:

永远不要忽略 SQL Server 中的排序警告

我的 SQL 服务器?

Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64) 2016 年 6 月 17 日 19:14:09 版权所有 (c) Microsoft Corporation Enterprise Edition(64 位),Windows NT 6.3(内部版本 9600:)(管理程序)

我的硬件?

运行以下查询以查找硬件:

-- 来自 SQL Server 2012 的硬件信息

SELECT cpu_count AS [Logical CPU Count], hyperthread_ratio AS …
Run Code Online (Sandbox Code Playgroud)

performance sql-server memory execution-plan sort-operator query-performance

22
推荐指数
1
解决办法
2万
查看次数

寻找,你将在分区表上扫描...

我在 PCMag 中阅读了 Itzik Ben-Gan 的这些文章:

搜索,您应扫描第 I 部分:当优化器未优化
搜索时,您应扫描第 II 部分:升序键

我目前的所有分区表都存在“最大分组”问题。我们使用Itzik Ben-Gan 提供的技巧来获取 max(ID),但有时它不会运行:

DECLARE @MaxIDPartitionTable BIGINT
SELECT  @MaxIDPartitionTable = ISNULL(MAX(IDPartitionedTable), 0)
FROM    ( SELECT    *
          FROM      ( SELECT    partition_number PartitionNumber
                      FROM      sys.partitions
                      WHERE     object_id = OBJECT_ID('fct.MyTable')
                                AND index_id = 1
                    ) T1
                    CROSS APPLY ( SELECT    ISNULL(MAX(UpdatedID), 0) AS IDPartitionedTable
                                  FROM      fct.MyTable s
                                  WHERE     $PARTITION.PF_MyTable(s.PCTimeStamp) = PartitionNumber
                                            AND UpdatedID <= @IDColumnThresholdValue
                                ) AS o
        ) AS T2;
SELECT @MaxIDPartitionTable 
Run Code Online (Sandbox Code Playgroud)

我得到这个计划

在此处输入图片说明

但是 45 分钟后,看看读数

reads …
Run Code Online (Sandbox Code Playgroud)

performance sql-server partitioning query-performance

21
推荐指数
1
解决办法
1066
查看次数

哈希键探测和残差

比如说,我们有一个这样的查询:

select a.*,b.*
from 
a join b
on a.col1=b.col1
and len(a.col1)=10
Run Code Online (Sandbox Code Playgroud)

假设上述查询使用 Hash Join 并具有残差,则探测键将为col1,残差将为len(a.col1)=10

但是在查看另一个示例时,我可以看到探针和残差是同一列。以下是对我想说的内容的详细说明:

询问:

select *
from T1 join T2 on T1.a = T2.a 
Run Code Online (Sandbox Code Playgroud)

执行计划,突出显示探测和残差:

在此处输入图片说明

测试数据:

create table T1 (a int, b int, x char(200))
create table T2 (a int, b int, x char(200))

set nocount on
declare @i int
set @i = 0
while @i < 1000
  begin
      insert T1 values (@i * 2, @i * 5, @i)
    set @i = @i …
Run Code Online (Sandbox Code Playgroud)

performance sql-server execution-plan database-internals query-performance

21
推荐指数
1
解决办法
4255
查看次数

关于诊断“有时”慢查询的建议

我有一个存储过程,它通过覆盖索引从索引视图返回结果。通常,它运行得很快(~10 毫秒),有时它可以运行长达 8 秒。

这是一个随机执行示例(注意:这不是一个缓慢的执行,但是除了传递的值之外,查询文本是相同的):

declare @p2 dbo.IdentityType
insert into @p2 values(5710955)
insert into @p2 values(5710896)
insert into @p2 values(5710678)
insert into @p2 values(5710871)
insert into @p2 values(5711103)
insert into @p2 values(6215197)
insert into @p2 values(5710780)

exec ListingSearch_ByLocationAndStatus @statusType=1,@locationIds=@p2
Run Code Online (Sandbox Code Playgroud)

这是 SPROC:

ALTER PROCEDURE [dbo].[ListingSearch_ByLocationAndStatus]
    @LocationIds IdentityType READONLY,
    @StatusType TINYINT
AS
BEGIN
    SET NOCOUNT ON;

    SELECT      -- lots of fields
    FROM        [dbo].[ListingSearchView][a] WITH (NOEXPAND)
    INNER JOIN  @LocationIds [b] ON [a].[LocationId] = [b].[Id]
    WHERE       [a].[StatusType] = @statusType
    OPTION (RECOMPILE);
Run Code Online (Sandbox Code Playgroud)

(注意:我OPTION (RECOMPILE) …

performance sql-server sql-server-2012 azure-vm query-performance

21
推荐指数
1
解决办法
919
查看次数

在 T-SQL 中使用 IF 会削弱或破坏执行计划缓存吗?

有人向我建议,在 t-SQL 批处理中使用 IF 语句对性能有害。我试图找到一些确认或验证这个断言。我使用的是 SQL Server 2005 和 2008。

断言是以下批次:-

IF @parameter = 0
 BEGIN
  SELECT ... something
 END

ELSE
 BEGIN
  SELECT ... something else
 END
Run Code Online (Sandbox Code Playgroud)

SQL Server 无法重用生成的执行计划,因为下一次执行可能需要不同的分支。这意味着 SQL Server 将从执行计划中完全删除一个分支,因为它已经可以确定当前执行需要哪个分支。这是真的吗?

此外,在这种情况下会发生什么:-

IF EXISTS (SELECT ....)
 BEGIN
  SELECT ... something
 END

ELSE
 BEGIN
  SELECT ... something else
 END
Run Code Online (Sandbox Code Playgroud)

无法提前确定将执行哪个分支?

performance sql-server-2005 sql-server-2008 sql-server query-performance

20
推荐指数
3
解决办法
7422
查看次数

根据我正在更新的行数,使用完全不同的计划的 T-SQL 查询

我有一个带有“TOP (X)”子句的 SQL UPDATE 语句,我正在更新值的行大约有 40 亿行。当我使用“TOP (10)”时,我得到一个几乎立即执行的执行计划,但是当我使用“TOP (50)”或更大时,查询永远不会(至少,在我等待时不会)完成,并且它使用完全不同的执行计划。较小的查询使用带有一对索引查找和嵌套循环连接的非常简单的计划,其中完全相同的查询(在 UPDATE 语句的 TOP 子句中具有不同的行数)使用涉及两个不同索引查找的计划、表线轴、并行性和一堆其他复杂性。

我使用了“OPTION (USE PLAN...)”来强制它使用由较小查询生成的执行计划——当我这样做时,我可以在几秒钟内更新多达 100,000 行。我知道查询计划很好,但 SQL Server 只会在只涉及少量行时自行选择该计划 - 我的更新中任何相当大的行数都会导致次优计划。

我认为并行性可能是罪魁祸首,所以我设置MAXDOP 1了查询,但没有效果 - 这一步已经消失,但糟糕的选择/性能没有。我sp_updatestats今天早上也跑了,以确保这不是原因。

我附上了两个执行计划 - 越短的执行计划也越快。此外,这里是有问题的查询(值得注意的是,我包含的 SELECT 在小行数和大行数的情况下似乎都很快):

    update top (10000) FactSubscriberUsage3
               set AccountID = sma.CustomerID
    --select top 50 f.AccountID, sma.CustomerID
      from FactSubscriberUsage3 f
      join dimTime t
        on f.TimeID = t.TimeID
      join #mac sma
        on f.macid = sma.macid
       and t.TimeValue between sma.StartDate and sma.enddate 
     where f.AccountID = 0 --There's a filtered index …
Run Code Online (Sandbox Code Playgroud)

performance sql-server execution-plan query-performance

20
推荐指数
1
解决办法
2410
查看次数

SQL Server 中的海量数据和性能

我编写了一个带有 SQL Server 后端的应用程序,用于收集和存储大量记录。我已经计算出,在高峰期,平均记录量大约为每天 3-40 亿条(运行 20 小时)。

我最初的解决方案(在我完成数据的实际计算之前)是让我的应用程序将记录插入到我的客户查询的同一个表中。显然,这会很快崩溃并烧毁,因为不可能查询插入了这么多记录的表。

我的第二个解决方案是使用 2 个数据库,一个用于应用程序接收的数据,另一个用于客户端就绪数据。

我的应用程序将接收数据,将其分成大约 10 万条记录的批次,然后批量插入到临时表中。在大约 100k 条记录之后,应用程序将使用与之前相同的架构即时创建另一个临时表,并开始插入到该表中。它将在具有 10 万条记录的作业表中创建一条记录,并且 SQL Server 端的存储过程会将数据从临时表移动到客户端就绪的生产表,然后删除我的应用程序创建的表临时表。

除了具有作业表的临时数据库外,两个数据库都具有相同的 5 个表集,具有相同的架构。临时数据库在大量记录将驻留的表上没有完整性约束、键、索引等。如下所示,表名是SignalValues_staging. 目标是让我的应用程序尽快将数据发送到 SQL Server。动态创建表以便轻松迁移的工作流程非常有效。

以下是我的临时数据库中的 5 个相关表,以及我的工作表:

临时表 我编写的存储过程处理从所有临时表中移动数据并将其插入到生产中。下面是我的存储过程的一部分,它从临时表插入到生产中:

-- Signalvalues jobs table.
SELECT *
      ,ROW_NUMBER() OVER (ORDER BY JobId) AS 'RowIndex'
INTO #JobsToProcess
FROM 
(
    SELECT JobId 
           ,ProcessingComplete  
           ,SignalValueStagingTableName AS 'TableName'
           ,(DATEDIFF(SECOND, (SELECT last_user_update
                              FROM sys.dm_db_index_usage_stats
                              WHERE database_id = DB_ID(DB_NAME())
                                AND OBJECT_ID = OBJECT_ID(SignalValueStagingTableName))
                     ,GETUTCDATE())) SecondsSinceLastUpdate
    FROM SignalValueJobs
) cte
WHERE cte.ProcessingComplete = 1 …
Run Code Online (Sandbox Code Playgroud)

performance sql-server sql-server-2014 query-performance

20
推荐指数
2
解决办法
2万
查看次数

SQL Server - 在嵌套的非确定性视图堆栈中处理字符串的本地化

在分析数据库时,我遇到了一个视图,该视图引用了一些非确定性函数,对于此应用程序池中的每个连接,这些函数每分钟被访问1000-2500 次。一个简单的视图产生以下执行计划:SELECT

在此处输入图片说明 在此处输入图片说明 在此处输入图片说明 在此处输入图片说明

对于少于一千行且每隔几个月可能会看到一两行更改的视图来说,这似乎是一个复杂的计划。但以下其他注意事项会变得更糟:

  1. 嵌套视图是不确定的,所以我们不能索引它们
  2. 每个视图引用多个 UDFs 来构建字符串
  3. 每个 UDF 包含嵌套 UDFs 以获取本地化语言的 ISO 代码
  4. 堆栈中的视图使用s返回的附加字符串构建器UDF作为JOIN谓词
  5. 每个视图堆被视为一个表,这意味着有INSERT/ UPDATE/DELETE在每个触发器来写入底层表
  6. 在视图上,这些触发器使用CURSORSEXEC存储过程作为参考更多的这些串建设UDF秒。

这对我来说似乎很糟糕,但我只有几年的 TSQL 经验。也越来越好!

看来开发人员认为这是一个好主意,这样做是为了让存储的几百个字符串可以根据从UDF特定于模式的a 返回的字符串进行翻译。

这是堆栈中的一个视图,但它们都同样糟糕:

CREATE VIEW [UserWKStringI18N]
AS
SELECT b.WKType, b.WKIndex
    , CASE
       WHEN ISNULL(il.I18NID, N'') = N''
       THEN id.I18NString
       ELSE il.I18nString
       END AS WKString
    ,CASE
       WHEN ISNULL(il.I18NID, N'') …
Run Code Online (Sandbox Code Playgroud)

performance sql-server sql-server-2008-r2 view functions query-performance

20
推荐指数
1
解决办法
1037
查看次数

a=0 and b=0 and ... z=0 vs a+b+c+d=0 的性能

这是一个我似乎无法找到答案的简单问题。

在性能方面,如果我有一个WHERE条款,例如a=0 and b=0 and ... z=0,如果我用 替换该条件,我会获得任何性能a+b+...+z=0吗?

换句话说,通过替换以下内容是否有任何性能提升

Select * 
From MyTable 
Where A=0 and B=0 and C=0 and D=0...
Run Code Online (Sandbox Code Playgroud)

Select * 
From MyTable 
Where A+B+C+D=0...
Run Code Online (Sandbox Code Playgroud)

我知道它可以依赖于索引,但为此目的,我们只说不存在索引。算术运算符 (+) 的性能是否比“OR”或“AND”逻辑运算符更好?

我的印象是加法比使用 AND 或 OR 的多个条件表现得更好。

检测结果

在 420 万行的表上

返回行其中 A=0 B=0 和 C=0 -> 351748 行

添加 (A+B+C=0) 需要 5 秒,而逻辑条件 A=0 和 B=0 和 C=0 需要 11 秒。

另一方面

返回行 其中 A<>0 B<>0 或 C<>0 -> 3829750 行 58 秒

返回行 …

performance sql-server query-performance

20
推荐指数
3
解决办法
5048
查看次数