简体   繁体   中英

Very slow Clustered Index Seek when there's a WHERE clause

I have an important SQL query that is performing too slowly. I pinpointed its performance issues to a view. Here is (roughly) what the view looks like:

Without WHERE clause

-- the 'top 100' isn't part of the view, but I've added it for testing purposes
SELECT  top 100
    fs.*,  
    fss.Status,  
    fss.CreateDateTimeUtc StatusDateTimeUtc,  
    fss.IsError,  
    fss.CorrelationId  
  FROM dbo.FormSubmission fs WITH (NOLOCK)  
  CROSS APPLY (  
    SELECT TOP 1  
      FormId,  
      SubmissionId,  
      Status,  
      CreateDateTimeUtc,  
      IsError,  
      CorrelationId  
    FROM dbo.FormSubmissionStatus x WITH (NOLOCK)  
    WHERE x.FormId = fs.FormId AND x.SubmissionId = fs.SubmissionId  
    ORDER BY CreateDateTimeUtc DESC  
  ) fss

If I run this, it's pretty quick. Here are some metrics and the execution plan:

  • 00:00:00.441
  • Table 'FormSubmissionStatus'. Scan count 102, logical reads 468
  • Table 'FormSubmission'. Scan count 1, logical reads 4

在此处输入图像描述


With WHERE clause

However, as soon as I add this WHERE clause, it gets much slower.

where status in ('Transmitted', 'Acknowledging')

Metrics and exeuction plan:

  • 00:00:15.1984
  • Table 'FormSubmissionStatus'. Scan count 4145754, logical reads 17619490
  • Table 'FormSubmission'. Scan count 1, logical reads 101978

在此处输入图像描述


Index attempt

I tried various types of new indexes and I haven't seen any real improvements. Here is an example of one:

create index ix_fss_datetime_formId_submissionId_status 
on FormSubmissionStatus (CreateDateTimeUtc) include (formId, submissionId, status)
where status in ('Transmitted', 'Acknowledging')

What else can I try to speed this up?

If it helps to know, the PK for this table is a composite of FormId (uniqueidentifier), SubmissionId (varchar50), Status(varchar50), and CreateDateTimeUtc(datetime2)

Update

Per @J.Salas's suggestion in the comments, I tried putting the WHERE clase in the subquery and saw a massive improvement (~700ms execution time vs the ~15s).

This isn't a solution, since I can't have that where clause in my view (the query that uses this view adds the WHERE clause). However, it does point to the subquery being a problem. Is there a way I could restructure it? Maybe do the subquery as a temp table and join on fs?

Looking at the query plan I do not hold hold much hope that the following could help. But your view query could be reformulated to use a CTE and ROW_NUMBER() instead of CROSS APPLY . I believe the following is equivalent in meaning:

WITH fss AS (SELECT 
      FormId,  
      SubmissionId,  
      Status,  
      CreateDateTimeUtc,  
      IsError,  
      CorrelationId,
      ROW_NUMBER() OVER (PARTITION BY FormId, SubmissionId ORDER BY CreateDateTimeUtc DESC) AS RN
    FROM dbo.FormSubmissionStatus)
SELECT  
    fs.*,  
    fss.Status,  
    fss.CreateDateTimeUtc StatusDateTimeUtc,  
    fss.IsError,  
    fss.CorrelationId  
  FROM dbo.FormSubmission fs
 INNER JOIN fss
    ON fss.FormId = fs.FormId
   AND fss.SubmissionId = fs.SubmissionId
 WHERE fss.RN = 1;

The APPLY operator in your original query is saying for ever row in fs run this query. Which if taken literally would cause that second query to run many many times. However SQL Server is free to optimize the plan so that the results are as if the subquery fss was run once per row of fs . So it may not be able to optimize the above any better.

For indexes I would try on (FormId, SubmissionId, CreateDateTimeUtc DESC) maybe with INCLUDE (Status) . But really anything besides the FormId, SubmissionId, and CreateDateTimeUtc would depend on how the view is used.

Query tuning is a matter of educated guesses combined with trial and error. To get better information for making informed guesses something like Brent Ozar's SQL Server First Responder Kit can help get information on what is actually happening in production. How to use is beyond the scope of a single StackOverflow answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM