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 ():
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);
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);
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.
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?
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).