Sql server 2008 优化';s使用15%的cpu时间

Sql server 2008 优化';s使用15%的cpu时间,sql-server-2008,Sql Server 2008,下面的查询占用了sql server上%15的cpu时间 declare @JobQueueId int = NULL, @JobTypeId int = NULL, @JobTypeIdHasValue BIT = 0, @TargetId int = NULL, @TargetIdHasValue BIT = 0, @JobMessage nvarchar(max) = NULL, @ComputerName nvarchar(60) = NULL, @

下面的查询占用了sql server上%15的cpu时间

declare
  @JobQueueId int = NULL,   @JobTypeId int = NULL,   @JobTypeIdHasValue BIT = 0,   @TargetId int = NULL,   @TargetIdHasValue BIT = 0,   
  @JobMessage nvarchar(max) = NULL,   @ComputerName nvarchar(60) = NULL,   @ComputerNameHasValue BIT = 0,   @StartedOn datetime = NULL,   
  @StartedOnHasValue BIT = 0,   @CompletedOn datetime = NULL,   @CompletedOnHasValue BIT = 0,   @SkipOrderedBy datetime = NULL,   
  @SkipOrderedByHasValue BIT = 0,   @SkipOrderedOn datetime = NULL,   @SkipOrderedOnHasValue BIT = 0,   @Attempts int = NULL,   
  @AttemptsHasValue BIT = 0,   @FailResult nvarchar(max) = NULL,   @FailResultHasValue BIT = 0,   @CreatedBy uniqueidentifier = NULL,   
  @CreatedOn datetime = NULL  



  SET TRANSACTION ISOLATION LEVEL READ COMMITTED    

  SELECT   [JobQueueId],   [JobTypeId],   [TargetId],   [JobMessage],   [ComputerName],   [StartedOn],   [CompletedOn],   [SkipOrderedBy],     [SkipOrderedOn],   [Attempts],   FailResult],   [CreatedBy],   [CreatedOn]  
  FROM      [dbo].[JobQueue]  

  WHERE   
  ([JobQueueId] = @JobQueueId OR @JobQueueId IS NULL)    
  AND ([JobTypeId] = @JobTypeId OR (@JobTypeId IS NULL AND @JobTypeIdHasValue = 0))   
  AND ([TargetId] = @TargetId OR (@TargetId IS NULL AND @TargetIdHasValue = 0))   
  AND ([JobMessage] = @JobMessage OR @JobMessage IS NULL)   
  AND ([ComputerName] = @ComputerName OR (@ComputerName IS NULL AND @ComputerNameHasValue = 0))   
  AND ([StartedOn] = @StartedOn OR (@StartedOn IS NULL AND @StartedOnHasValue = 0))   
  AND ([CompletedOn] = @CompletedOn OR (@CompletedOn IS NULL AND @CompletedOnHasValue = 0))   
  AND ([SkipOrderedBy] = @SkipOrderedBy OR (@SkipOrderedBy IS NULL AND @SkipOrderedByHasValue = 0))   
  AND ([SkipOrderedOn] = @SkipOrderedOn OR (@SkipOrderedOn IS NULL AND @SkipOrderedOnHasValue = 0))   
  AND ([Attempts] = @Attempts OR (@Attempts IS NULL AND @AttemptsHasValue = 0))   
  AND ([FailResult] = @FailResult OR (@FailResult IS NULL AND @FailResultHasValue = 0))   
  AND ([CreatedBy] = @CreatedBy OR @CreatedBy IS NULL)   
  AND ([CreatedOn] = @CreatedOn OR @CreatedOn IS NULL)    

有人能提供一些指针来帮助我优化这个查询吗?

因为查询可能会缓存一个支持特定参数的计划,所以不同的参数很可能不会从该计划中受益匪浅(搜索“参数嗅探”,您会发现这是一个非常常见的问题)。有两种选择:

  • 添加到语句中。由于每次编译,这将花费更多的成本,但它至少是可预测的,并且您不应该有这些巨大的波动,对于某些参数,它在半秒钟内运行,而对于其他参数,它运行很长时间
  • 使用可避免使用以前缓存的参数进行优化
  • 打开服务器级选项(通过
    sp_configure
    针对临时工作负载进行优化(请参阅和),并将查询更改为使用动态SQL。换句话说,按如下方式构建查询:

    DECLARE @sql NVARCHAR(MAX);
    
    SET @sql = N'SELECT ... FROM [dbo].[JobQueue] WHERE 1=1';
    
    IF @JobQueueId IS NOT NULL
      SET @sql = @sql + N' AND JobQueueId = @JobQueueId';
    
    -- ... repeat for other params
    
    EXEC sp_executesql 
      @sql,
      N'@JobQueueId INT, ..., @CreatedOn DATETIME',
      @JobQueueId, ..., @CreatedOn;
    

  • 另请参见:

    这是一个非常糟糕的查询。and和OR(及其模式)的绝对数量使得任何关于索引的静态推理都是徒劳的。它如此糟糕的主要原因是因为它是“通用的”:很多应该是静态的工作(比如检查@JobQueueId是否为null)都留给了SQL server


    由于您不会从任何类型的查询准备中获益,因此您应该以动态方式构造查询,并让db server针对每个特定情况优化您的选择。

    尝试查看执行计划。评估你的指数,它们有意义吗?表上有索引吗?你还需要更多吗?看看我已经通过DTA运行了查询。大约有13个索引和42个统计数据。我只需要在这一点上重做查询。它只是消耗了服务器,一分钟运行很多次。我将第二、第三和第四个@driis所说的内容。我最近花了几天时间试图找出一个性能问题,结果是由于几个索引丢失。Tuning Advisor没有给我任何建议。它有所有需要的索引,我想你已经知道了。目前,存储过程是使用csla开发的。但我认为它需要一些改进,我认为你的第三个选择可能是最好的选择。谢谢你的意见。当我们做出改变时,我会记住这一点。