Truy vấn chạy chậm trong trang web thử nghiệm trong lần thực hiện đầu tiên. Tại sao?


7

Tôi tìm thấy truy vấn này bằng cách xem một trang web thử nghiệm với trình hồ sơ sql cho bất cứ điều gì mất hơn 10 giây. Tôi đã đưa mã ra khỏi trình biên dịch sql và vào studio sql, nơi nó có thể thực thi nhanh chóng. Hành vi "chạy đầu tiên" chậm có thể được thiết lập lại bằng cách sử dụng DBCPC DROPCLEANBUFFERS.

Đây là truy vấn chậm:

exec sp_executesql N'SELECT [t0].*
FROM [dbo].[MyTable] AS [t0]
WHERE [t0].[ParentID] IN (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17, @p18, @p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26, @p27, @p28, @p29, @p30, @p31, @p32, @p33, @p34, @p35, @p36, @p37, @p38, @p39, @p40, @p41, @p42, @p43, @p44, @p45, @p46, @p47, @p48, @p49, @p50, @p51, @p52, @p53, @p54, @p55, @p56, @p57, @p58, @p59, @p60, @p61, @p62, @p63, @p64, @p65, @p66, @p67, @p68, @p69, @p70, @p71, @p72, @p73, @p74)',N'@p0 int,@p1 int,@p2 int,@p3 int,@p4 int,@p5 int,@p6 int,@p7 int,@p8 int,@p9 int,@p10 int,@p11 int,@p12 int,@p13 int,@p14 int,@p15 int,@p16 int,@p17 int,@p18 int,@p19 int,@p20 int,@p21 int,@p22 int,@p23 int,@p24 int,@p25 int,@p26 int,@p27 int,@p28 int,@p29 int,@p30 int,@p31 int,@p32 int,@p33 int,@p34 int,@p35 int,@p36 int,@p37 int,@p38 int,@p39 int,@p40 int,@p41 int,@p42 int,@p43 int,@p44 int,@p45 int,@p46 int,@p47 int,@p48 int,@p49 int,@p50 int,@p51 int,@p52 int,@p53 int,@p54 int,@p55 int,@p56 int,@p57 int,@p58 int,@p59 int,@p60 int,@p61 int,@p62 int,@p63 int,@p64 int,@p65 int,@p66 int,@p67 int,@p68 int,@p69 int,@p70 int,@p71 int,@p72 int,@p73 int,@p74 int',@p0=121888,@p1=317624,@p2=278130,@p3=299426,@p4=128786,@p5=553917,@p6=169682,@p7=316993,@p8=319430,@p9=321347,@p10=377276,@p11=388570,@p12=233344,@p13=304376,@p14=318493,@p15=318190,@p16=144455,@p17=342559,@p18=309867,@p19=258251,@p20=139296,@p21=530970,@p22=288191,@p23=127107,@p24=547572,@p25=617531,@p26=238898,@p27=606923,@p28=267113,@p29=140833,@p30=122554,@p31=298846,@p32=562964,@p33=554626,@p34=414874,@p35=534996,@p36=614977,@p37=230423,@p38=261899,@p39=149666,@p40=179537,@p41=148420,@p42=262955,@p43=298094,@p44=575449,@p45=246861,@p46=572334,@p47=172152,@p48=529420,@p49=129074,@p50=266589,@p51=194619,@p52=376201,@p53=608389,@p54=162335,@p55=405965,@p56=125671,@p57=146195,@p58=538850,@p59=575254,@p60=129485,@p61=243677,@p62=615828,@p63=236197,@p64=343015,@p65=294449,@p66=562013,@p67=138933,@p68=614729,@p69=561779,@p70=-1,@p71=-1,@p72=-1,@p73=-1,@p74=-1

Đây là định nghĩa bảng, với các chỉ mục:

CREATE TABLE [dbo].[MyTable] (
[MyID] [int] IDENTITY (1, 1) NOT NULL ,
[GrandParentID] [int] NOT NULL ,
[ParentID] [int] NOT NULL ,
[Col1] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[Col2] [nvarchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[Col3] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[Col4] [nvarchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[Col5] [decimal](18, 2) NULL ,
[Col6] [char] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[Col7] [char] (4) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
[OtherKey] [int] NULL ,
[Col8] [nvarchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Col9] [datetime] NULL ,
[Col10] [nvarchar] (150) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
 CONSTRAINT [PK__7E8439BE] PRIMARY KEY  CLUSTERED 
(
    [MyID]
)  ON [PRIMARY] 
) ON [PRIMARY]

CREATE  INDEX [MyTable_ParentID] ON [dbo].[MyTable]([ParentID]) WITH  FILLFACTOR = 90 ON [PRIMARY]
CREATE  INDEX [MyTable_OtherKey] ON [dbo].[MyTable]([OtherKey] DESC ) WITH  FILLFACTOR = 90 ON [PRIMARY]
CREATE  INDEX [MyTable_GrandParentID] ON [dbo].[MyTable]([GrandParentID]) ON [PRIMARY]

Dưới đây là thời gian và IO:

-- Test site - first run:
(7064 row(s) affected)
Table 'MyTable'. Scan count 71, logical reads 49255, physical reads 3, read-ahead reads 13160, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
 SQL Server Execution Times:
   CPU time = 140 ms,  elapsed time = 30400 ms.

-- Test site - second run:
(7064 row(s) affected)
Table 'MyTable'. Scan count 71, logical reads 29054, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
 SQL Server Execution Times:
   CPU time = 78 ms,  elapsed time = 169 ms.

-- Production site - first run:
(7064 row(s) affected)
Table 'MyTable'. Scan count 71, logical reads 50513, physical reads 3, read-ahead reads 13157, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
 SQL Server Execution Times:
   CPU time = 62 ms,  elapsed time = 276 ms.

-- Production site - second run:
(7064 row(s) affected)
Table 'MyTable'. Scan count 71, logical reads 29054, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
 SQL Server Execution Times:
   CPU time = 63 ms,  elapsed time = 262 ms.

Trang web thử nghiệm và trang sản xuất được thiết lập theo cùng một cách - các tệp cơ sở dữ liệu nằm trên một ổ cứng ảo duy nhất, được hỗ trợ bởi SAN cân bằng tải nhiều đĩa.

Kế hoạch thực hiện:

constantscan -> sort -> lồng nhau -> tìm kiếm chỉ mục -> vòng lặp lồng nhau -> tra cứu khóa


1
Thật không may là "Chọn t. * .." làm cho việc sử dụng chỉ mục che phủ trở nên vô dụng. Bằng cách đó, bạn có thể đã thoát khỏi những Tra cứu quan trọng tốn kém đó, đây sẽ là phần đầu tiên tôi tham gia. Bạn có đang sử dụng Entity Framework (hoặc bất cứ thứ gì tương tự) không?
Mary

Đây là một truy vấn được biên dịch LinqToSql.
Amy B

Câu trả lời:


12

Chà, lần đầu tiên bạn chạy truy vấn, nó phải tải nó từ đĩa; sau đó nó sử dụng bộ nhớ, nhanh hơn nhiều so với đĩa. Nếu bạn xóa bộ đệm, về cơ bản bạn sẽ xóa tất cả dữ liệu đó khỏi bộ nhớ, vì vậy lần sau khi bạn yêu cầu dữ liệu, nó phải tải lại từ đĩa. Hãy nghĩ về đĩa so với bộ nhớ như rùa so với thỏ. Ngoài các kịch bản thử nghiệm, bạn muốn các truy vấn của bạn thường chạy từ bộ đệm ấm và không nên cố ý xóa vùng đệm bằng cách sử dụng DBCC DROPCLEANBUFFERS;.


Có, tôi chỉ sử dụng DROPCLEANBUFFERS để tạo lại trường hợp thực hiện truy vấn đầu tiên. Trang web sản xuất dường như không quan tâm đến việc thực hiện truy vấn đầu tiên. Bạn có suy nghĩ gì về điều đó không?
Amy B

2
Tôi không biết "dường như không quan tâm" nghĩa là gì. Bạn đang nói trong sản xuất, nó luôn luôn chậm bất kể hay nó luôn luôn nhanh? Có bao nhiêu dữ liệu trong sản xuất so với thử nghiệm? Làm thế nào về bộ nhớ, sự khác biệt trong hệ thống I / O, vv? Bạn đã so sánh các kế hoạch thực hiện trong sản xuất so với thử nghiệm? Chúng tôi không phải là người đọc tâm trí rất tốt. :-)
Aaron Bertrand

1
Ý tôi là I / O không phải là những gì bạn nghĩ, tôi đoán vậy. Ý tôi là hộp kiểm tra của bạn là một máy ảo với một số đĩa chậm iSCSI hoặc DAS 7200 RPM với dữ liệu / log / tempdb đều chia sẻ cùng một ổ đĩa và máy sản xuất của bạn đang sử dụng 15K SAS hoặc SSD với dữ liệu / log / tempdb được phân phối phù hợp, tạo ra I / O ít quan trọng? So sánh táo với táo rất quan trọng và khi bạn không và bạn muốn nhập liệu, bạn cần chia sẻ tất cả các chi tiết.
Aaron Bertrand

1
Ngoài ra, bạn đang nói về một kế hoạch thực hiện ước tính hoặc một kế hoạch thực hiện thực tế ? Quăng ra ước tính và mất actuals cho mỗi trong số bốn kịch bản bạn đã mô tả. Tốt nhất là sử dụng Plan Explorer , sẽ bao gồm tất cả các loại số liệu thời gian chạy hữu ích mà bạn sẽ không nhận được trực tiếp từ SSMS. Nếu bạn đánh giá phiên bản PRO, bạn thậm chí sẽ nhận được số liệu thống kê chờ cho phiên của mình (vì vậy hãy tạo kế hoạch cho từng trong bốn kịch bản trong các tab riêng biệt).
Aaron Bertrand

5
@DavidB Bạn có nhận ra rằng sự khác biệt phải là hậu quả của một số khác biệt giữa hai môi trường? Bây giờ liên quan đến sự khác biệt này, ngay cả các chuyên gia giỏi nhất (bao gồm Aaron) chỉ có thể đoán, trong khi bạn có thể theo dõi nó.
dezso

6

Tôi rất muốn nghe một số chuyên gia điều chỉnh hiệu suất nhưng từ những gì tôi có thể thấy với thông tin được trình bày, 13160 đọc trước đang đọc đang tải nó vào bộ nhớ. Lần thứ 2 nó đọc nó từ bộ nhớ và nhanh hơn nhiều. Trở thành một hệ thống ảo có thể có nghĩa là IOPS được chia sẻ và nó có thể làm tình hình trở nên trầm trọng hơn khi nó tải nó vào bộ đệm. Khi bạn xóa bộ đệm, nó cần đọc lại từ đĩa.

Nếu bạn có thể thu thập số liệu thống kê chờ đợi cho điều này, chúng tôi sẽ biết nếu đó là câu trả lời đúng. Tôi hy vọng có lẽ 10 giây PAGELATCHIO sẽ xuất hiện. Sử dụng liên kết này để lấy các sự kiện mở rộng cho một hoạt động. Chạy truy vấn đầu tiên, nhận thông tin sự kiện mở rộng, chạy lại mà không xóa bộ nhớ và nhận thông tin và sự kiện mở rộng. Nó sẽ hiển thị đĩa io là vấn đề lần đầu tiên.


3

Tác động chính đối với truy vấn của bạn là do LOOKUP KEY có chi phí 77%. Bạn có thể thoát khỏi tra cứu khóa bằng cách tạo chỉ mục bao phủ hoặc chỉ mục cột được bao gồm.

Chỉ số bao phủ che phủ sẽ bao gồm các truy vấn bằng cách bao gồm tất cả các cột cần thiết.

Chỉ số được bao gồm sẽ cho phép bạn bao gồm các cột bổ sung để chúng được lưu trữ với chỉ mục nhưng không phải là một phần của cây chỉ mục. Điều này có một lợi thế là yêu cầu ít dung lượng lưu trữ hơn (nếu chỉ số của bạn rất lớn, tính bằng GB).

Vì vậy, nếu bạn tạo một chỉ mục không được nhóm trên MyTable với các cột được bao gồm, nó sẽ loại bỏ việc tra cứu khóa và ở đó bằng cách cải thiện hiệu năng truy vấn.

Nhìn vào thuộc tính Tra cứu khóa và xem những cột nào được yêu cầu.

ví dụ: nếu thuộc tính tra cứu khóa hiển thị MyID trong danh sách đầu ra thì bên dưới

CREATE NONCLUSTERED INDEX [MyTable_ParentID_included] ON [dbo].[MyTable]
(
       [ParentID] 
)
INCLUDE ([MyID])  ON [PRIMARY]
GO

Một số giải thích tốt có thể được tìm thấy Giảm tra cứu chính

EDIT: Chỉ cần lưu ý rằng bạn đang sử dụng

SELECT [t0].*
FROM [dbo].[MyTable] AS [t0] .....

Ứng dụng có yêu cầu tất cả các cột từ bảng cơ sở không? điều này sẽ phủ nhận việc sử dụng các cột được bao gồm.


1
Mặc dù rõ ràng hữu ích để cải thiện hiệu suất nói chung, câu hỏi đặt ra là tại sao truy vấn chậm trong lần chạy đầu tiên và nhanh cho các lần chạy tiếp theo. Hoặc ít nhất đó là cách tôi đọc nó.
Aaron Bertrand

Trong khi một chỉ số bao phủ sẽ làm giảm IO, nó sẽ có giá rất cao trong không gian. Tôi chưa sẵn sàng để đề xuất chỉ số 8G tại thời điểm này. Câu hỏi của tôi là - tại sao lần chạy đầu tiên của truy vấn hoạt động tốt trong sản xuất, nhưng lại kém trong thử nghiệm?
Amy B

Nó phụ thuộc vào rất nhiều yếu tố - Aaron và Ali đã đề cập. Là máy chủ ảo, tất cả các cài đặt cấu hình giống nhau trên thử nghiệm và SẢN PHẨM, dung lượng RAM, phiên bản máy chủ sql và gói dịch vụ giống nhau trên thử nghiệm và SẢN PHẨM?
Kin Shah
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.