Tôi đã có vấn đề này từ lâu, tôi đã tìm thấy một cách giải quyết phù hợp với tôi và quên nó đi.
Nhưng bây giờ có câu hỏi về SO vì vậy tôi sẵn sàng đưa vấn đề này lên.
Có một khung nhìn tham gia vài bảng theo cách rất đơn giản (đơn hàng + dòng đơn hàng).
Khi được truy vấn mà không có một where
mệnh đề, khung nhìn trả về vài triệu dòng.
Tuy nhiên, không ai từng gọi nó như thế. Truy vấn thông thường là
select * from that_nasty_view where order_number = 123456;
Điều này trả về khoảng 10 hồ sơ trong số 5m.
Một điều quan trọng: chế độ xem chứa chức năng cửa sổ rank()
, được phân vùng chính xác theo trường sử dụng chế độ xem luôn được truy vấn:
rank() over (partition by order_number order by detail_line_number)
Bây giờ, nếu chế độ xem này được truy vấn với các tham số bằng chữ trong chuỗi truy vấn, chính xác như được hiển thị ở trên, nó sẽ trả về các hàng ngay lập tức. Kế hoạch thực hiện là tốt:
- Chỉ mục tìm kiếm trên cả hai bảng bằng cách sử dụng các chỉ số trên
order_number
(trả về 10 hàng). - Tính toán các cửa sổ trên kết quả nhỏ được trả về.
- Lựa chọn.
Tuy nhiên, khi chế độ xem được gọi theo cách tối ưu, mọi thứ trở nên khó chịu:
Index scan
trên tất cả các bảng bỏ qua các chỉ số. Trả về 5m hàng.- Tham gia rất lớn.
- Tính toán các cửa sổ trên tất cả
partition
s (khoảng 500k cửa sổ). Filter
để lấy 10 hàng trong số 5m.- Lựa chọn
Điều này xảy ra trong mọi trường hợp khi các tham số có liên quan. Nó có thể là SSMS:
declare @order_number int = 123456;
select * from that_nasty_view where order_number = @order_number;
Nó có thể là máy khách ODBC, chẳng hạn như Excel:
select * from that_nasty_view where order_number = ?
Hoặc nó có thể là bất kỳ máy khách nào khác sử dụng tham số và không ghép nối sql.
Nếu chức năng cửa sổ được loại bỏ khỏi chế độ xem, nó sẽ chạy hoàn toàn nhanh chóng, bất kể nó có được truy vấn hay không.
Cách giải quyết của tôi là loại bỏ chức năng vi phạm và áp dụng lại ở giai đoạn sau.
Nhưng, những gì cho? Đây có thực sự là một lỗi trong cách SQL Server 2008 xử lý các chức năng của cửa sổ không?
order_number
không phải là khóa chính. Đó là int not null
với chỉ mục không bao gồm trên nó trong cả hai bảng.
OPTION (RECOMPILE)
trợ giúp?