Hiệu suất bảng tạm thời kém trên các giá trị cũ


8

Tôi đang gặp một vấn đề kỳ lạ xảy ra khi truy cập các hồ sơ lịch sử trong một bảng tạm thời. Các truy vấn truy cập vào các mục cũ hơn trong bảng tạm thời thông qua mệnh đề phụ AS OF mất nhiều thời gian hơn các truy vấn trên các mục lịch sử gần đây.

Bảng lịch sử được tạo bởi SQL Server (bao gồm một chỉ mục được nhóm trên các cột ngày và sử dụng nén trang), tôi đã thêm 50 triệu hàng vào bảng lịch sử và các truy vấn của tôi đã truy xuất khoảng 25.000 hàng.

Tôi đã cố gắng xác định nguyên nhân gốc rễ của vấn đề nhưng chưa thể xác định được. Cho đến nay tôi đã thử nghiệm:

  • Tạo một bảng thử nghiệm với 50 triệu hàng với chỉ mục được nhóm để xem liệu sự chậm lại chỉ đơn giản là do khối lượng. Tôi đã có thể truy xuất 25K hàng tại thời gian không đổi (~ 400ms).
  • Loại bỏ nén trang khỏi bảng lịch sử. Điều đó không ảnh hưởng đến thời gian truy xuất nhưng đã làm tăng đáng kể kích thước của bảng.
  • Tôi đã thử truy cập trực tiếp vào các hàng của bảng lịch sử bằng cột ID so với cột ngày. Đây là nơi mọi thứ thú vị hơn một chút. Tôi có thể truy cập các hàng cũ hơn trong bảng ở mức ~ 400ms trong đó với mệnh đề phụ AS OF sẽ mất ~ 1200ms. Tôi đã thử lọc trên bảng thử nghiệm của mình trên cột ngày và nhận thấy sự chậm lại tương tự khi so sánh với lọc trên cột ID. Điều này khiến tôi tin rằng các so sánh ngày là đằng sau một số chậm lại.

Tôi muốn xem xét điều này nhiều hơn nhưng tôi cũng muốn chắc chắn rằng tôi không sủa sai cây. Đầu tiên, có ai khác gặp phải hành vi tương tự khi truy cập dữ liệu lịch sử cũ hơn trong một bảng tạm thời (chúng tôi chỉ nhận thấy sự chậm lại vượt qua 10 triệu hàng)? Thứ hai, một số chiến lược tôi có thể sử dụng để cách ly nguyên nhân gốc rễ của vấn đề hiệu năng (tôi mới bắt đầu xem xét các kế hoạch thực hiện nhưng nó vẫn hơi khó hiểu đối với tôi)?

Kế hoạch thực hiện

Đây là các truy vấn truy xuất đơn giản: đầu tiên truy cập các hàng cũ hơn, thứ hai truy cập các hàng mới hơn.

Hàng cũ hơn ~ 1200ms thời gian thực hiện

Hàng gần đây ~ 350ms thời gian thực hiện

Bảng chi tiết

Đây là các cột trong bảng thời gian. Bảng lịch sử có cùng các cột nhưng không có khóa chính (theo yêu cầu của bảng lịch sử): Cột bảng tạm thời

Dưới đây là các chỉ số trên bảng lịch sử: Các chỉ số trên bảng lịch sử

Câu trả lời:


6

Trong một bình luận từ Zane về câu hỏi của bạn, ông tuyên bố:

... Có vẻ như một phần của vấn đề của bạn là bạn đang đọc 50 triệu hàng để trả lại 20 nghìn trong kế hoạch.

Đây thực sự là vấn đề. Không có chỉ mục có sẵn để đẩy một số hoặc tất cả các vị từ xuống công cụ lưu trữ. Microsoft khuyến nghị chiến lược lập chỉ mục cơ bản này cho các bảng tạm thời trong bài viết Tài liệu Xem xét và Hạn chế của Bảng tạm thời :

Chiến lược lập chỉ mục tối ưu sẽ bao gồm một chỉ mục lưu trữ các cột được phân cụm và / hoặc một chỉ mục lưu trữ hàng cây B trên bảng hiện tại và một chỉ mục lưu trữ phân cụm trên bảng lịch sử để có kích thước và hiệu suất lưu trữ tối ưu. Nếu bạn tạo / sử dụng bảng lịch sử của riêng mình, chúng tôi khuyên bạn nên tạo loại chỉ mục này bao gồm các cột thời gian bắt đầu bằng cột cuối kỳ để tăng tốc truy vấn tạm thời cũng như tăng tốc các truy vấn là một phần của tính nhất quán dữ liệu kiểm tra. Bảng lịch sử mặc định có một chỉ mục cửa hàng được phân cụm được tạo cho bạn dựa trên các cột thời gian (kết thúc, bắt đầu). Tối thiểu, một chỉ số cửa hàng không phân cụm được khuyến nghị

Phrasing của điều đó là một chút bối rối (với tôi, dù sao). Nhưng điều đáng nói là bạn có thể tạo các chỉ mục này để cải thiện hiệu suất một số, nếu không muốn nói là khá nhiều:

Chỉ số NC trên bảng hiện tại, dẫn đầu với SysEndTime :

CREATE NONCLUSTERED INDEX IX_SysEndTime_SysStartTime 
ON dbo.Benefits (SysEndTime, SysStartTime)
/*INCLUDE (ideally, include your other important fields here)*/;

Điều này sẽ cho phép bạn tránh đọc một số hàng trong bảng hiện tại bằng cách tìm đến thời gian kết thúc thích hợp.

CCI trên bảng lịch sử

CREATE CLUSTERED COLUMNSTORE INDEX ix_BenefitsHistory
ON dbo.BenefitsHistory
WITH (DROP_EXISTING = ON);

Điều này sẽ cho phép bạn có được chế độ hàng loạt trên bảng lịch sử, giúp quét nhanh hơn nhiều.

Chỉ số NC trên bảng hiện tại, dẫn đầu với SysStartTime :

Xem câu trả lời của Paul cho câu hỏi Cách hiệu quả nhất để truy xuất phạm vi ngày để biết thêm chi tiết về lý do tại sao việc lập chỉ mục cho các truy vấn phạm vi ngày là khó khăn. Dựa trên logic ở đó, sẽ hợp lý hơn khi thêm một chỉ mục NC khác vào bảng hiện tại dẫn đến SysStartTime, để trình tối ưu hóa có thể chọn sử dụng cái nào dựa trên thống kê và các tham số cụ thể của truy vấn của bạn:

CREATE NONCLUSTERED INDEX IX_SysStartTime_SysEndTime
ON dbo.Benefits (SysStartTime, SysEndTime)
/*INCLUDE (ideally, include your other important fields here)*/;

Việc tạo 3 chỉ mục được nêu ở trên đã tạo ra sự khác biệt đáng kể trong việc sử dụng tài nguyên trong các trường hợp thử nghiệm của tôi. Tôi thiết lập một trường hợp thử nghiệm chạy hai truy vấn trả về 1,5 triệu hàng. Cả lịch sử và bảng hiện tại có 50 triệu hàng).

Lưu ý: Để giảm chi phí SSMS, tôi đã chạy thử nghiệm với tùy chọn "Hủy kết quả sau khi thực hiện" được bật.

Kế hoạch thực hiện - Chỉ mục mặc định


Thời gian đọc logic: 1.330.612 Thời gian CPU: 00: 00: 14.718
Thời gian đã trôi qua: 00: 00: 06.198

Kế hoạch thực hiện - Với các chỉ số được mô tả ở trên

Số lần đọc logic: 27.656 (8.111 hàng lưu trữ + 19.545 cột lưu trữ)
Thời gian CPU: 00: 00: 01.828
Thời gian đã trôi qua: 00: 00: 01.150

Như bạn có thể thấy, cả 3 biện pháp đều giảm đáng kể - bao gồm tổng thời gian đã trôi qua, từ 6 giây xuống còn 1 giây.


Tùy chọn khác được trình bày trong bài viết Tài liệu là từ bỏ hai chỉ mục NC trên bảng hiện tại để thay thế cho một chỉ mục của cửa hàng cột. Trong thử nghiệm của tôi, hiệu suất rất giống với giải pháp lập chỉ mục được mô tả ở trên.


2

Các FOR SYSTEM TIME AS OF khoản cố gắng để trả lại dữ liệu vì nó tồn tại đồng thời nêu. Điều này có nghĩa là các bản cập nhật phải được khôi phục trong nội bộ, các bản xóa phải được "xóa" và các phần chèn phải được bỏ qua, dựa trên thời gian hệ thống của yêu cầu.

Càng xa trong thời gian AS OF càng xa, càng cần phải xác nhận nhiều công việc hơn để đảm bảo rằng bảng tạm thời tồn tại ở thời điểm hệ thống đã chỉ định và do đó, truy vấn sẽ mất nhiều thời gian hơn.

NẾU bảng dữ liệu chỉ là bảng ghi nhật ký và không có thay đổi nào được thực hiện đối với dữ liệu, sau đó sử dụng ngày được ghi và một chỉ mục sẽ trả về dữ liệu nhanh hơn và ổn định hơn. Có nên sử dụng các tính năng tạm thời trong trường hợp này là không cần thiết. Tuy nhiên, nếu các thay đổi được thực hiện cho các hàng (trừ chèn), thì sử dụng tính năng bảng tạm thời là cách duy nhất để trả về dữ liệu chính xác được yêu cầu (trạng thái của bảng khi nó tồn tại vào thời điểm cụ thể đó), và bạn sẽ chỉ cần chấp nhận chi phí bổ sung của các truy vấn tạm thời.

Lưu ý: "Rollback" không phải là rollback thực tế. Các bảng tạm thời sử dụng hai bảng - bảng Hiện tại và bảng Lịch sử. Khi một hàng được thay đổi, một bản sao của phiên bản trước được chèn vào bảng Lịch sử với phạm vi thời gian mà hàng đó hợp lệ. Nếu bạn chèn một hàng vào ngày 20/10/2018 10: 20: 20,18, hãy cập nhật một giá trị vào ngày 25/10/2018 10: 25: 20,18 và cập nhật lại vào lúc 12/01/2018 12: 01: 20,18, bạn có phiên bản mới nhất của hàng trong bảng Hiện tại có ngày bắt đầu là 12/01/2018 12: 01: 20,18 và hai hàng trong bảng lịch sử với các phạm vi hợp lệ từ 10/20 đến 25/10/2018 và 10 / 25 đến 12/01/2018


Cảm ơn vì sự trả lời! Điều đó chắc chắn có ý nghĩa trực quan, nhưng tôi không tìm thấy bất kỳ đề cập nào về loại hành vi đó trong các tài liệu tôi đọc (tôi chỉ đi qua những điều cơ bản của bảng tạm thời trong tài liệu của MS). Bạn có biết bất kỳ tài liệu nào mô tả hành vi chi tiết hơn một chút không?
Ebrahim Behbahani
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.