Có thể buộc trình tối ưu hóa loại bỏ các bảng không liên quan trong chế độ xem được phân vùng này không?


22

Tôi đang thử nghiệm các kiến ​​trúc khác nhau cho các bảng lớn và một đề xuất mà tôi đã thấy là sử dụng chế độ xem được phân vùng, theo đó một bảng lớn được chia thành một loạt các bảng nhỏ hơn, "phân vùng".

1 , 2 , 3 , 4

Khi thử nghiệm phương pháp này, tôi đã phát hiện ra điều gì đó không có ý nghĩa gì đối với tôi. Khi tôi lọc trên "cột phân vùng" trên chế độ xem thực tế, trình tối ưu hóa chỉ tìm kiếm trên các bảng có liên quan. Ngoài ra, nếu tôi lọc trên cột đó trên bảng thứ nguyên, trình tối ưu hóa sẽ loại bỏ các bảng không cần thiết.

Tuy nhiên, nếu tôi lọc trên một số khía cạnh khác của kích thước, trình tối ưu hóa sẽ tìm kiếm trên PK / CI của mỗi bảng cơ sở.

Dưới đây là các truy vấn trong câu hỏi:

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where o.ObservationDateKey >= 20000101
    and o.ObservationDateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.DateKey >= 20000101
    and od.DateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.[Year] >= 2000 and od.[Year] < 2006
group by od.[Year];

bộ lọc thực tế trên khóa

bộ lọc mờ trên phím

bộ lọc mờ trên khía cạnh

Đây là một liên kết đến phiên SQL Sentry Plan Explorer.

Tôi đang làm việc trên thực tế phân vùng bảng lớn hơn để xem liệu tôi có loại bỏ phân vùng để đáp ứng theo cách tương tự.

Tôi nhận được loại bỏ phân vùng cho truy vấn (đơn giản) lọc trên một khía cạnh của thứ nguyên.

Trong thời gian này, đây là bản sao cơ sở dữ liệu chỉ thống kê:

https://gist.github.com/swasheck/9a22bf8a580995d3b2aa

Công cụ ước tính cardinality "cũ" có được một gói ít tốn kém hơn, nhưng đó là do ước tính cardinality thấp hơn trên mỗi chỉ số (không cần thiết) tìm kiếm.

Tôi muốn biết liệu có cách nào để tối ưu hóa sử dụng cột khóa khi lọc theo một khía cạnh khác của kích thước để nó có thể loại bỏ tìm kiếm trên các bảng không liên quan.

Phiên bản máy chủ SQL:

Microsoft SQL Server 2014 - 12.0.2000.8 (X64) 
    Feb 20 2014 20:04:26 
    Copyright (c) Microsoft Corporation
    Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)

Chỉ là một FYI .. luồng stat cuối cùng bị hỏngCREATE STATISTICS [_WA_Sys_00000008_2FCF1A8A] ON [dbo].[Observation_2010]([StationStateCode]) WITH STATS_STREAM = 0x01000000010000000000000000000000D4531EDB00000000D5080000000000009508000000000000AF030000AF000000020000000000000008D000340000000007000000E65DE0007DA5000076F9780000000000867704000000000000000000ABAAAA3C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Kin Shah

Có vẻ như tập lệnh cho cơ sở dữ liệu chỉ thống kê bị cắt ngắn. Tôi đã thử nhấp vào "xem toàn bộ tệp" và tải xuống mã zip, nhưng bằng cách nào đó tôi không có số liệu thống kê cho ObservationDatesbảng. Tôi không nhận được kế hoạch giống như Paul, ngay cả với 4199, và tôi nghĩ đây là lý do.
Geoff Patterson

@GeoffPatterson nó hoạt động với tôi. Bạn đã nhấp vào liên kết đến tập tin thô? gist.githubusercontent.com/swasheck/9a22bf8a580995d3b2aa/raw/ , tuy nhiên, như Kin lưu ý, luồng thống kê cuối cùng bị hỏng: /
swasheck

Tôi đã nhấp vào liên kết cho các tập tin thô. Kịch bản không hoạt động (ngoại trừ vấn đề Kin lưu ý), nhưng không chứa bất kỳ logic nào để tạo số liệu thống kê ObservationDates. Cuối cùng tôi đã chạy UPDATE STATISTICS ObservationDates WITH ROWCOUNT = 10000bằng tay để có được kế hoạch mà Paul đã thể hiện.
Geoff Patterson

lẻ tạo một cơ sở dữ liệu mới và chạy tập lệnh đó tôi có các đối tượng thống kê (tốt, chúng là các chỉ mục), ObservationDatesvì vậy tôi không chắc điều gì đang xảy ra với điều đó. Ngoài ra, tôi cũng không thể có được kế hoạch paul được tạo ra. Tôi sẽ thử cập nhật để xem.
swasheck

Câu trả lời:


10

Kích hoạt cờ theo dõi 4199.

Tôi cũng đã phải phát hành:

UPDATE STATISTICS dbo.ObservationDates 
WITH ROWCOUNT = 73049;

để có được các kế hoạch hiển thị dưới đây. Thống kê cho bảng này đã bị thiếu trong quá trình tải lên. Con số 73.049 đến từ thông tin Cardinality trong tệp đính kèm Plan Explorer. Tôi đã sử dụng SQL Server 2014 SP1 CU4 (bản dựng 12.0.4436) với hai bộ xử lý logic, bộ nhớ tối đa được đặt thành 2048 MB và không có cờ theo dõi nào ngoài 4199.

Sau đó, bạn sẽ nhận được một kế hoạch thực hiện có tính năng loại bỏ phân vùng động:

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where 
    od.[Year] >= 2000 and od.[Year] < 2006
group by 
    od.[Year]
option (querytraceon 4199);

Kế hoạch mảnh:

Kế hoạch mảnh

Điều này có thể trông tệ hơn, nhưng Bộ lọc là tất cả các bộ lọc khởi động . Một vị ngữ ví dụ là:

Thuộc tính bộ lọc

Mỗi lần lặp của vòng lặp, vị từ khởi động được kiểm tra và chỉ khi nó trả về giá trị đúng thì Tìm kiếm chỉ mục cụm bên dưới nó được thực thi. Do đó, loại bỏ phân vùng động.

Điều này có lẽ không hoàn toàn hiệu quả như loại bỏ tĩnh, đặc biệt nếu kế hoạch song song.

Bạn có thể cần thử các gợi ý như MAXDOP 1, FAST 1hoặc FORCESEEKtrên khung nhìn để có được kế hoạch tương tự. Lựa chọn tối ưu hóa chi phí với các khung nhìn được phân vùng (như các bảng được phân đoạn) có thể khó khăn.

Vấn đề là bạn cần một kế hoạch có các bộ lọc khởi động để loại bỏ phân vùng động với các chế độ xem được phân vùng.


Các truy vấn với các USE PLANgợi ý được nhúng : (thông qua gist.github.com):


1
Thông tin tuyệt vời, cảm ơn Paul! Tôi đã tự hỏi sau khi tôi viết câu trả lời của mình tại sao không có cách nào SQL Server có thể thực hiện loại bỏ này. Hóa ra là có, tôi chưa từng thấy nó trước đây!
Geoff Patterson

6

Quan sát của tôi luôn là bạn phải chỉ định giá trị (hoặc phạm vi giá trị) cho cột phân vùng một cách rõ ràng trong truy vấn để có được "loại bỏ bảng" trong chế độ xem được phân vùng. Điều này dựa trên kinh nghiệm sử dụng các chế độ xem được phân vùng trong sản xuất từ ​​SQL Server 2000 đến SQL Server 2014.

SQL Server không có khái niệm về toán tử nối vòng trong đó động cơ có thể tự động nhắm mục tiêu tìm kiếm trực tiếp vào bảng thích hợp ở phía bên trong của vòng lặp dựa trên giá trị của hàng ở phía bên ngoài của vòng lặp. Tuy nhiên, như câu trả lời của Paul giải thích , có khả năng một kế hoạch với các bộ lọc khởi động để tự động bỏ qua các bảng không liên quan ở phía bên trong của vòng lặp trong thời gian không đổi (trái ngược với logarit bằng cách thực sự tìm kiếm).

Lưu ý rằng đối với các bảng được phân đoạn, tuy nhiên, loại tìm kiếm này (đến một phân vùng cụ thể) được hỗ trợ.

Nếu bạn cố định sử dụng các chế độ xem được phân vùng, một tùy chọn khác là chia truy vấn của bạn thành nhiều truy vấn, chẳng hạn như:

-- Gather than the min/max values for the partition column
DECLARE @minDateKey INT,
        @maxDateKey INT
SELECT @minDateKey = MIN(DateKey),
        @maxDateKey = MAX(DateKey)
FROM dbo.ObservationDates od
WHERE od.[Year] >= 2000 and od.[Year] < 2006

-- Since I have a stats-only copy of the database, simulate having run the query above
-- (You can comment this out since you have the actual data.)
SELECT @minDateKey = 20000101, @maxDateKey = 20051231

-- Adjust the query to use the min/max values of the partition column
-- rather than filtering on a different column in the dimension table
select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
WHERE od.DateKey >= @minDateKey AND od.DateKey <= @maxDateKey
group by od.[Year]
-- Must use OPTION RECOMPILE; otherwise the plan will touch all tables because it
-- must do so in order to be valid for all values of the parameters!
OPTION (RECOMPILE)

Điều này mang lại kế hoạch sau đây. Hiện tại có một truy vấn bổ sung vào bảng thứ nguyên, nhưng truy vấn trên bảng thực tế (có lẽ lớn hơn nhiều) được tối ưu hóa.

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


Liệu hiệu quả tương tự có thể đạt được nếu bạn kết hợp truy vấn đầu tiên vào truy vấn thứ hai mà không cần truy vấn các biến?
Andriy M

@AndriyM Nếu tôi hiểu đúng về bạn, câu trả lời là không, hiệu ứng tương tự sẽ không đạt được và kế hoạch truy vấn sẽ chạm vào tất cả các bảng trong chế độ xem được phân vùng nếu bạn cố gắng kết hợp hai truy vấn. Nếu bạn đã thực hiện truy vấn đầu tiên, sau đó dán các giá trị 2000010120051231thay vì các biến (hoặc thực hiện một số tương tự thông qua hai truy vấn riêng biệt trong ứng dụng của bạn), thì có, sẽ đạt được hiệu quả tương tự mà không cần sử dụng các biến.
Geoff Patterson
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.