Chúng tôi có một cơ sở dữ liệu lớn, khoảng 1TB, chạy SQL Server 2014 trên một máy chủ mạnh mẽ. Mọi thứ hoạt động tốt trong một vài năm. Khoảng 2 tuần trước, chúng tôi đã bảo trì đầy đủ, bao gồm: Cài đặt tất cả các bản cập nhật phần mềm; xây dựng lại tất cả các chỉ mục và tập tin DB nhỏ gọn. Tuy nhiên, chúng tôi không mong đợi rằng ở giai đoạn nhất định, việc sử dụng CPU của DB tăng hơn 100% đến 150% khi tải thực tế là như nhau.
Sau rất nhiều lần khắc phục sự cố, chúng tôi đã thu hẹp nó thành một truy vấn rất đơn giản, nhưng chúng tôi không thể tìm ra giải pháp. Truy vấn cực kỳ đơn giản:
select top 1 EventID from EventLog with (nolock) order by EventID
Nó luôn mất khoảng 1,5 giây! Tuy nhiên, một truy vấn tương tự với "desc" luôn mất khoảng 0 ms:
select top 1 EventID from EventLog with (nolock) order by EventID desc
PTable có khoảng 500 triệu hàng; EventID
là cột chỉ mục cụm chính (được đặt hàng ASC
) với kiểu dữ liệu của bigint (cột Danh tính). Có nhiều luồng chèn dữ liệu vào bảng ở trên cùng (EventID lớn hơn) và có 1 luồng xóa dữ liệu từ phía dưới (EventID nhỏ hơn).
Trong SMSS, chúng tôi đã xác minh rằng hai truy vấn luôn sử dụng cùng một kế hoạch thực hiện:
Quét chỉ mục cụm;
Số hàng ước tính và thực tế là cả 1;
Ước tính và số lần thực hiện thực tế là cả 1;
Ước tính chi phí I / O là 8500 (Có vẻ là cao)
Nếu chạy liên tiếp, chi phí Truy vấn là 50% cho cả hai.
Tôi cập nhật chỉ số thống kê with fullscan
, vấn đề vẫn tồn tại; Tôi xây dựng lại chỉ mục một lần nữa, và vấn đề dường như đã biến mất trong nửa ngày, nhưng đã trở lại.
Tôi đã bật thống kê IO với:
set statistics io on
sau đó chạy hai truy vấn liên tiếp và tìm thấy thông tin sau:
(Đối với truy vấn đầu tiên, truy vấn chậm)
Bảng 'PTable'. Quét số 1, đọc logic 407670, đọc vật lý 0, đọc trước 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.
(Đối với truy vấn thứ hai, truy vấn nhanh)
Bảng 'PTable'. Quét số 1, đọc logic 4, đọc vật lý 0, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.
Lưu ý sự khác biệt rất lớn trong việc đọc logic. Chỉ số được sử dụng trong cả hai trường hợp.
Phân mảnh chỉ số có thể giải thích một chút, nhưng tôi tin rằng tác động là rất nhỏ; và vấn đề chưa từng xảy ra trước đây. Một bằng chứng khác là nếu tôi chạy một truy vấn như:
select * from EventLog with (nolock) where EventID=xxxx
Ngay cả khi tôi đặt xxxx thành các EventID nhỏ nhất trong bảng, truy vấn luôn nhanh như chớp.
Chúng tôi đã kiểm tra và không có vấn đề khóa / chặn.
Lưu ý: Tôi chỉ cố gắng đơn giản hóa vấn đề trên. "PTable" thực sự là "EventLog"; những PID
là EventID
.
Tôi nhận được thử nghiệm kết quả tương tự mà không có NOLOCK
gợi ý.
Ai có thể giúp đỡ?
Các kế hoạch thực hiện truy vấn chi tiết hơn trong XML như sau:
https://www.brentozar.com/pastetheplan/?id=SJ3eiVnob
https://www.brentozar.com/pastetheplan/?id=r1rOjVhoZ
Tôi không nghĩ rằng nó quan trọng để cung cấp các tuyên bố tạo bảng. Nó là một cơ sở dữ liệu cũ và đã chạy hoàn toàn tốt trong một thời gian dài cho đến khi bảo trì. Chúng tôi đã thực hiện rất nhiều nghiên cứu và thu hẹp nó vào thông tin được cung cấp trong câu hỏi của tôi.
Bảng được tạo bình thường với EventID
cột là khóa chính, là identity
cột kiểu bigint
. Tại thời điểm này, tôi đoán vấn đề là với sự phân mảnh chỉ số. Ngay sau khi xây dựng lại chỉ số, vấn đề dường như đã biến mất trong nửa ngày; Nhưng tại sao nó lại quay lại nhanh như vậy ...?