Làm thế nào để ước tính hàng có thể được cải thiện để giảm cơ hội tràn sang tempdb


11

Tôi nhận thấy rằng khi có sự cố tràn vào các sự kiện tempdb (gây ra các truy vấn chậm) thì thường các ước tính hàng bị tắt cho một phép nối cụ thể. Tôi đã thấy các sự kiện tràn xảy ra với phép nối và băm và chúng thường tăng thời gian chạy gấp 3 đến 10 lần. Câu hỏi này liên quan đến cách cải thiện các ước tính hàng theo giả định rằng nó sẽ làm giảm cơ hội các sự kiện tràn.

Số hàng thực tế 40k.

Đối với truy vấn này, kế hoạch hiển thị ước tính hàng xấu (11,3 hàng):

select Value
  from Oav.ValueArray
 where ObjectId = (select convert(bigint, Value) NodeId
                     from Oav.ValueArray
                    where PropertyId = 3331  
                      and ObjectId = 3540233
                      and Sequence = 2)
   and PropertyId = 2840
option (recompile);

Đối với truy vấn này, gói hiển thị ước tính hàng tốt (56k hàng):

declare @a bigint = (select convert(bigint, Value) NodeId
                       from Oav.ValueArray
                      where PropertyId = 3331
                        and ObjectId = 3540233
                        and Sequence = 2);

select Value
  from Oav.ValueArray
 where ObjectId = @a               
   and PropertyId = 2840
option (recompile);

Số liệu thống kê hoặc gợi ý có thể được thêm vào để cải thiện các ước tính hàng cho trường hợp đầu tiên không? Tôi đã thử thêm số liệu thống kê với các giá trị bộ lọc cụ thể (property = 2840) nhưng không thể kết hợp chính xác hoặc có lẽ nó bị bỏ qua vì ObjectId không xác định tại thời điểm biên dịch và có thể chọn trung bình trên tất cả các ObjectIds.

Có chế độ nào trong đó nó sẽ thực hiện truy vấn thăm dò trước và sau đó sử dụng chế độ đó để xác định các ước tính hàng hoặc nó phải bay một cách mù quáng?

Thuộc tính đặc biệt này có nhiều giá trị (40k) trên một vài đối tượng và bằng không trên đại đa số. Tôi sẽ rất vui với một gợi ý trong đó số lượng hàng dự kiến ​​tối đa cho một liên kết nhất định có thể được chỉ định. Đây là một vấn đề ám ảnh nói chung vì một số tham số có thể được xác định một cách linh hoạt như một phần của phép nối hoặc sẽ được đặt tốt hơn trong chế độ xem (không hỗ trợ các biến).

Có bất kỳ tham số nào có thể được điều chỉnh để giảm thiểu cơ hội tràn sang tempdb (ví dụ: bộ nhớ tối thiểu cho mỗi truy vấn) không? Kế hoạch mạnh mẽ không có tác dụng lên dự toán.

Chỉnh sửa 2013.11.06 : Trả lời các bình luận và thông tin bổ sung:

Dưới đây là hình ảnh kế hoạch truy vấn. Các cảnh báo là về vị ngữ / tìm kiếm vị trí với convert ():

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Theo nhận xét của @Aaron Bertrand, tôi đã thử thay thế convert () dưới dạng thử nghiệm:

create table Oav.SeekObject (
       LookupId bigint not null primary key,
       ObjectId bigint not null
);

insert into Oav.SeekObject (
   LookupId, ObjectId
) VALUES (
   1, 3540233
) 

select Value
  from Oav.ValueArray
 where ObjectId = (select ObjectId 
                     from Oav.SeekObject 
                    where LookupId = 1)
   and PropertyId = 2840
option (recompile);

nhập mô tả hình ảnh ở đây

Là một điểm quan tâm kỳ lạ nhưng thành công, cũng cho phép nó rút ngắn quá trình tra cứu:

select Value
  from Oav.ValueArray
 where ObjectId = (select ObjectId 
                     from Oav.ValueArray
                    where PropertyId = 2840
                      and ObjectId = 3540233
                      and Sequence = 2)
   and PropertyId = 2840
option (recompile);

nhập mô tả hình ảnh ở đây

Cả hai đều liệt kê một tra cứu khóa thích hợp nhưng chỉ những cái đầu tiên liệt kê một "Đầu ra" của ObjectId. Tôi đoán rằng chỉ ra thứ hai là thực sự ngắn mạch?

Ai đó có thể xác minh xem các đầu dò một hàng có được thực hiện để giúp ước tính hàng không? Có vẻ sai khi giới hạn tối ưu hóa chỉ ước tính biểu đồ khi tra cứu PK một hàng có thể cải thiện đáng kể độ chính xác của tra cứu vào biểu đồ (đặc biệt là nếu có tiềm năng hoặc lịch sử tràn). Khi có 10 trong số các tham gia phụ này trong một truy vấn thực, lý tưởng là chúng sẽ xảy ra song song.

Một lưu ý phụ, vì sql_variant lưu trữ loại cơ sở của nó (SQL_VariANT_PROPERTY = BaseType) trong chính trường đó, tôi sẽ mong đợi một chuyển đổi () gần như không tốn kém miễn là nó có thể chuyển đổi "trực tiếp" int hoặc có thể int để bigint). Vì điều đó không được biết đến vào thời gian biên dịch nhưng có thể được người dùng biết đến, có lẽ hàm "AssumeType (loại, ...)" cho sql_variants sẽ cho phép chúng được xử lý trong suốt hơn.


1
Dự đoán đầu tiên là việc chuyển đổi sang bigint sẽ loại bỏ các ước tính của bạn (kế hoạch truy vấn sẽ có cảnh báo về điều đó trong SQL Server 2012), nhưng mặt khác, truy vấn phụ của bạn không bao giờ có thể trả về bất kỳ thứ gì ngoài 0 hoặc 1 hàng cho một truy vấn thành công. Sẽ rất thú vị khi xem các kế hoạch truy vấn mà bạn có. Có lẽ là một liên kết đến phiên bản XML.
Mikael Eriksson

2
Bạn có được gì khi có nội tuyến phụ? Tôi khuyên bạn nên rút nó ra một cách tổng thể rõ ràng hơn và vì nó dẫn đến ước tính tốt hơn, tại sao không sử dụng phương pháp đó?
Aaron Bertrand

2
Phiên bản nào của SQL Server? Bạn có thể cung cấp bảng & chỉ số DDL và các đốm thống kê (cột đơn và đa cột) cho các bảng để chúng tôi có thể xem chi tiết vấn đề không? Chia tách truy vấn bằng cách declare @a bigint = bạn đã làm dường như là một giải pháp tự nhiên đối với tôi, tại sao điều đó không được chấp nhận?
Paul White 9

2
Tôi đoán thiết kế của bạn là một thiết kế EAV (rất đơn giản) buộc bạn phải sử dụng CONVERT()trong các cột và sau đó tham gia chúng. Điều này chắc chắn không hiệu quả là hầu hết các trường hợp. Trong trường hợp cụ thể này, chỉ có một giá trị được chuyển đổi để có thể đó không phải là vấn đề nhưng bạn có chỉ số nào trên bảng? Các thiết kế EAV thường hoạt động tốt, chỉ với việc lập chỉ mục thích hợp (có nghĩa là rất nhiều chỉ mục trong các bảng thường hẹp).
ypercubeᵀᴹ

@Paul White, cho đến khi tách ra ... đó là một giải pháp cho trường hợp này. Nhưng đối với tổng quát / phức tạp hơn, tôi hầu như không muốn từ bỏ sự song song và dễ đọc. Giả sử tôi có 10 trong số này là các truy vấn phụ (một số phức tạp hơn) trong một truy vấn nhưng chỉ có 5 cần phải "chín" trước khi phần còn lại của truy vấn có thể bắt đầu - muốn tránh phải tìm ra 5 truy vấn nào.
crokusek

Câu trả lời:


7

Tôi sẽ không bình luận về sự cố tràn, tempdb hoặc gợi ý vì truy vấn có vẻ khá đơn giản để cần nhiều sự cân nhắc. Tôi nghĩ trình tối ưu hóa của SQL-Server sẽ thực hiện công việc của nó khá tốt, nếu có các chỉ mục phù hợp với truy vấn.

Và việc chia thành hai truy vấn của bạn là tốt vì nó cho thấy các chỉ mục nào sẽ hữu ích. Phần đầu tiên:

(select convert(bigint, Value) NodeId
 from Oav.ValueArray
 where PropertyId = 3331  
   and ObjectId = 3540233
   and Sequence = 2)

cần một chỉ mục trên (PropertyId, ObjectId, Sequence)bao gồm cả Value. Tôi sẽ làm cho nó UNIQUEan toàn. Truy vấn sẽ đưa ra lỗi dù sao trong thời gian chạy nếu có nhiều hơn một hàng được trả về, vì vậy thật tốt để đảm bảo trước rằng điều này sẽ không xảy ra, với chỉ mục duy nhất:

CREATE UNIQUE INDEX
    PropertyId_ObjectId_Sequence_UQ
  ON Oav.ValueArray
    (PropertyId, ObjectId, Sequence) INCLUDE (Value) ;

Phần thứ hai của truy vấn:

select Value
  from Oav.ValueArray
 where ObjectId = @a               
   and PropertyId = 2840

cần một chỉ số (PropertyId, ObjectId)bao gồm Value:

CREATE INDEX
    PropertyId_ObjectId_IX
  ON Oav.ValueArray
    (PropertyId, ObjectId) INCLUDE (Value) ;

Nếu hiệu quả không được cải thiện hoặc các chỉ mục này không được sử dụng hoặc vẫn có sự khác biệt trong ước tính hàng xuất hiện, thì cần phải xem xét thêm về truy vấn này.

Trong trường hợp đó, các chuyển đổi (cần thiết từ thiết kế EAV và lưu trữ các kiểu dữ liệu khác nhau trong cùng một cột) là nguyên nhân có thể xảy ra và giải pháp phân tách của bạn (như @AAron Bertrand và @Paul White nhận xét) truy vấn thành hai phần có vẻ tự nhiên và con đường để đi. Một thiết kế lại để có các kiểu dữ liệu khác nhau trong các cột tương ứng của chúng có thể là một kiểu khác.


Các bảng có các chỉ số bao gồm - tôi nên đã nói rằng trong câu hỏi. Ví dụ thực sự là một tham gia phụ cung cấp một truy vấn lớn hơn, đó là lý do tại sao có tất cả sự ồn ào về sự cố tràn tempdb.
crokusek

5

Là một câu trả lời một phần cho câu hỏi rõ ràng về việc cải thiện số liệu thống kê ...

Lưu ý rằng các ước tính hàng ngay cả đối với trường hợp riêng biệt bị phá vỡ vẫn bị giảm 10 lần (4k so với 40k dự kiến).

Biểu đồ thống kê có khả năng trải quá mỏng cho thuộc tính đó vì đây là bảng hàng dài (dọc), 3,5M và thuộc tính cụ thể đó rất thưa thớt.

Tạo một số liệu thống kê bổ sung (hơi dư thừa với số liệu thống kê IX) cho thuộc tính thưa thớt:

create statistics [STAT_ValueArray_ObjPropValue_WhereProp2840] ON [Oav].[ValueArray](ObjectId, PropertyId, Value)
where PropertyId = 2840

Bản gốc:

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Với convert () được gỡ bỏ (thích hợp):

nhập mô tả hình ảnh ở đây

Với convert () đã bị xóa (ciruit ngắn):

nhập mô tả hình ảnh ở đây

Vẫn bị giảm ~ 2 lần vì> 99,9% đối tượng không có Thuộc tính 2840 được xác định trên tất cả. Trong thực tế, chỉ với trường hợp thử nghiệm này, thuộc tính chỉ tồn tại trên 1 trong 200k Đối tượng riêng biệt của bảng hàng 3,5M. Thật tuyệt vời nó đã đến gần thực sự. Điều chỉnh bộ lọc để có ít ObjectIds hơn,

create statistics [STAT_ValueArray_ObjPropValue_WhereProp2840] ON [Oav].[ValueArray](ObjectId, PropertyId, Value)
where PropertyId = 2840 and ObjectId >= 3540000 and ObjectId < 3541000

create statistics [STAT_ValueArray_ObjPropValue_WhereProp2840] ON [Oav].[ValueArray](ObjectId, PropertyId, Value)
where PropertyId = 2840 and ObjectId = 3540233;

Hmm, không có thay đổi ... Đã sao lưu thêm "với quét toàn bộ" vào cuối thống kê (có thể là lý do tại sao hai phần trước không hoạt động) và có:

create statistics [STAT_ValueArray_ObjPropValue_WhereProp2840] ON [Oav].[ValueArray](ObjectId, PropertyId, Value)
where PropertyId = 2840 with full scan;

nhập mô tả hình ảnh ở đây

Yay Vì vậy, trong một bảng có độ thẳng đứng cao với độ bao phủ rộng rãi IX, việc thêm các số liệu thống kê được lọc bổ sung dường như là một cải tiến lớn (đáng chú ý là các tổ hợp phím thưa thớt nhưng có nhiều biến thể).


Một liên kết đến một số vấn đề có vấn đề với số liệu thống kê nhiều cột.
crokusek
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.