SQL Server: Sử dụng cơ sở dữ liệu kép cho hiệu suất?


7

Chúng tôi có cơ sở dữ liệu SQL lưu trữ nhật ký sử dụng ứng dụng cho khoảng 3000 PC. Những PC này gửi dữ liệu sử dụng của họ đến máy chủ SQL khoảng 10-20 lần mỗi ngày. Chúng tôi chỉ lưu trữ 60 ngày sử dụng ứng dụng gần đây nhất, nhưng khách hàng yêu cầu chúng tôi không thanh lọc dữ liệu nữa. Bây giờ chúng ta có dữ liệu khoảng một năm (khoảng 6.000.000 hàng), cơ sở dữ liệu SQL đang gặp phải một số vấn đề về hiệu suất. Không quan trọng, nhớ bạn, nhưng nhiều hơn bất kỳ cơ sở dữ liệu khác chúng tôi có. Có một số lượng đáng kể các bản ghi được thêm vào mỗi giờ ( bản ghi mở ứng dụng ) và trong vòng vài giờ, bản ghi đó sẽ được cập nhật chỉ một lần khi đóng ứng dụng liên quan . Đây là những cập nhật mà bạn có thể thấy thông qua SQL Activity Monitor đang mất nhiều thời gian để hoàn thành.

Truy vấn CẬP NHẬT đó rất đơn giản:

SELECT TOP 1 f_ID 
from tb_applicationusage 
WHERE f_application = 'xxxxxxx' AND 
      f_computername = 'xxxxxxxxx' AND 
      f_endtime IS NULL 
ORDER BY f_starttime DESC

Thực tế, nó tìm thấy ứng dụng phù hợp gần đây nhất bắt đầu cho một máy cụ thể chưa có ứng dụng liên quan đóng. Tôi không thể nghĩ ra một cách hiệu quả hơn để chạy truy vấn, vì vậy tôi đang xem xét phương án sau:

Di chuyển đến hai cơ sở dữ liệu:

  1. Cơ sở dữ liệu làm việc chỉ với hồ sơ trị giá 24 giờ gần đây nhất
  2. Cơ sở dữ liệu cuối cùng với tất cả các hồ sơ khác

Tôi không phải là chuyên gia SQL, vì vậy tôi có thể thiếu một số nhược điểm của phương pháp này. Mục tiêu sẽ là có một công việc Đại lý SQL chuyển các bản ghi đã hoàn thành sang cơ sở dữ liệu cuối cùng mỗi đêm. Sau đó, khi khách hàng muốn chạy các báo cáo hàng tháng của họ, tôi chỉ có thể có truy vấn báo cáo đó chỉ là cơ sở dữ liệu cuối cùng chứ không phải cơ sở dữ liệu hoạt động. Chỉ với 10.000 bản ghi để truy vấn trong cơ sở dữ liệu hoạt động thay vì 6.000.000, có vẻ hợp lý rằng nó sẽ hoạt động nhanh hơn. Nhưng một lần nữa, có vẻ đơn giản là tôi có thể thiếu một cái gì đó rõ ràng.

Phiên bản: Microsoft SQL Server 2008 R2


3
Những chỉ số INDEXnào tồn tại trên tb_applicationusage?
TT.

1
Bạn có thể cho chúng tôi một kế hoạch truy vấn mẫu và định nghĩa bảng không? Ngoài ra mẫu là một tuyên bố chọn không phải là một bản cập nhật. Nói chung là tốt hơn để cung cấp cho chúng tôi truy vấn chính xác gây ra sự cố thay vì một truy vấn tương tự. Đôi khi ma quỷ nằm trong các chi tiết và mẫu của bạn không thể hiện cùng một hiệu suất chậm.
Erik

Câu trả lời:


5

Bạn có thể làm tốt hơn hai cơ sở dữ liệu. Có hai điều bạn nên xem trong cơ sở dữ liệu hiện tại của mình trước khi loại bỏ một phần dữ liệu cũ:

  1. Chọn một chỉ số cụm tốt. Có ba quy tắc bạn nên tuân theo để chỉ mục được nhóm hoạt động tốt với dữ liệu này:

    1. Nó nên sử dụng một giá trị ngày càng tăng, để các bản ghi mới sẽ luôn thuộc về cuối bảng theo thứ tự cụm hoặc ít nhất là trong trang cuối cùng. Điều này đặc biệt quan trọng khi bạn có nhiều phần chèn, như trong trường hợp này. Một cái gì đó giống như một trường nhận dạng / tự động, nhưng bạn sẽ thấy ngay tại sao chúng ta có thể làm tốt hơn.
    2. Nó nên xác định duy nhất hoặc gần như duy nhất bản ghi, vì vậy các bản cập nhật cho bản ghi đóng ứng dụng sẽ nhanh chóng.
    3. Bạn sẽ có thể biết chỉ mục được phân cụm dựa trên các bản ghi đóng ứng dụng đi vào DB (điều này loại trừ cột nhận dạng từ trước đó).
    4. Bạn không muốn bất cứ điều gì thay đổi bởi ứng dụng đóng các bản ghi là một phần của chỉ mục, vì điều đó có thể buộc cơ sở dữ liệu cần phải di chuyển bản ghi đến một vị trí mới trên đĩa khi bạn cập nhật.

    Nếu có dấu thời gian tăng (ví dụ f_starttime:), điều đó có thể tốt cho trường đầu tiên trong chỉ mục, miễn là nó cũng là một phần của bản ghi đóng như được chỉ ra trong yêu cầu số 3. Thêm bất kỳ trường nào khác mà bạn sẽ cần để xác định duy nhất hoặc gần như duy nhất một bản ghi. Lưu ý rằng bạn vẫn có thể sử dụng cột nhận dạng cho bảng. Chỉ không sử dụng nó làm cột đầu tiên trong chỉ mục được nhóm. Dựa trên mã sql trong câu hỏi, tôi có thể đi với f_starttime, f_computername, f_application, f_ID.

    Ngay cả khi bạn đi với bảng phân tầng được đề xuất trong câu trả lời khác, những thay đổi chỉ số này vẫn có thể là một ý tưởng tốt.

  2. Phân vùng bảng. Phân vùng bảng giúp máy chủ db chỉ giữ các bản ghi gần đây trong bộ nhớ, để dữ liệu cũ hơn từ cùng một bảng có thể vẫn còn trên đĩa. Sql Server 2016 thậm chí sẽ cho phép bạn đẩy dữ liệu lịch sử lên bộ nhớ đám mây trên Azure thông qua Cơ sở dữ liệu Stretch .

Các đề xuất khác để giữ hồ sơ hoàn thành tách biệt với hồ sơ mở là tốt, quá. Mặc dù với gợi ý đó, mặc dù, lập chỉ mục và phân vùng bảng có thể giúp ích khi kích thước của bảng cho các bản ghi hoàn thành trở nên lớn. Bạn có thể bắt đầu xem xét việc chuyển dữ liệu cũ sang một db (được liên kết) riêng sau khi tất cả các tùy chọn này không thành công.

Mặc dù vậy, thực sự, Sql Server có thể dễ dàng xử lý sáu triệu bản ghi mà không cần dùng đến các loại thủ thuật này (tuy nhiên việc thay đổi chỉ mục vẫn có thể đáng làm). Bạn có chắc chắn máy chủ được cung cấp chính xác cho việc này? Bạn có thể làm chỉ đơn giản là thêm RAM vào máy chủ.

Cuối cùng, việc tách một cơ sở dữ liệu báo cáo khỏi cơ sở dữ liệu xử lý trực tiếp cũng rất phổ biến và hoàn toàn không phải là điều xấu. Đôi khi chúng tôi gọi đây là "Kho dữ liệu", mặc dù điều đó cũng thường liên quan đến thay đổi lược đồ và quy trình SSIS để di chuyển dữ liệu. Đây là một tính năng tốt để có, bởi vì nó ngăn ngừa một lỗi vô ý trong truy vấn phân tích dữ liệu gây ra các vấn đề về hiệu suất trong sản xuất. Bạn có thể thực hiện tốt nhất việc này thông qua phản ánh / chuyển nhật ký cơ sở dữ liệu sang một nô lệ chỉ đọc hoặc gần đây hơn thông qua Nhóm Luôn sẵn sàng.


Cảm ơn bạn đã trả lời rất chi tiết. @Hogan dưới đây cũng đề cập đến việc lập chỉ mục, nhưng đây không phải là khái niệm tôi quen thuộc. "Có thể lập chỉ mục" được đặt thành "Có" cho từng trường trong cơ sở dữ liệu, nhưng tôi không biết đó có phải là điều bạn đang nói không. Tôi có một cột ID mà không được sử dụng. Bố cục bảng hiện tại: i.imgur.com/c4sNaUy.jpg . Phương pháp tối ưu (bạn có một liên kết) để kích hoạt chỉ mục cụm này là gì?

Có thể lập chỉ mục để có chắc chắn không phải là điều tương tự. Tôi chắc chắn rằng chỉ mục được nhóm (khóa chính) trên bảng sử dụng các trường f_starttime, f_computername, f_application, f_endtime, f_ID, tương tự như những gì tôi đã đề xuất trong câu trả lời và đảm bảo đặt các cột theo chỉ mục theo thứ tự đó .
Joel Coehoorn

Cảm ơn bạn đã giúp đỡ cho đến nay. Tôi đã đọc nhiều nhất có thể về đề xuất của bạn. Tôi có các cột trong chỉ mục như bạn đã nêu, vì vậy câu hỏi cuối cùng của tôi là: Có nên đặt tùy chọn "Is Unique" thành "Có" và cũng nên đặt tùy chọn "Tạo thành cụm" thành "Có" không? Ảnh chụp màn hình của cài đặt: imgur.com/uQ3fF31.jpg
Beems

Bạn muốn "Được nhóm" thành "có" ở đây. "Là duy nhất" chỉ nên có nếu bạn có thể đảm bảo các cột đó sẽ luôn tham chiếu đến một bản ghi cụ thể. Nếu hai trường hợp của cùng một ứng dụng trên cùng một máy tính có thể báo cáo cùng một thời gian bắt đầu từ xa, bạn sẽ cần một cách để phân biệt các bản ghi hoặc bạn sẽ cần đặt "Là duy nhất" thành "Không" . Thông thường, bạn muốn các chỉ mục được nhóm của bạn là duy nhất; bạn muốn đặt thành "Có" nếu có thể. Tuy nhiên, điều đó là không bắt buộc và các va chạm trong trường hợp này sẽ đủ hiếm để tránh các vấn đề nếu bạn không thể đảm bảo điều đó
Joel Coehoorn

2
Nếu điều này có ích, tôi thực sự muốn nghe một số số trước và sau.
Joel Coehoorn

6

Hai điều

  1. Bạn không thực sự nói rằng bạn có một chỉ số trên bàn - tôi hy vọng điều này sẽ giải quyết vấn đề của bạn. Một chỉ mục trên f_application, f_computername, f_endtime, f_starttime sẽ khiến thời gian cập nhật của bạn trở nên nhỏ bé chỉ với các bản ghi 6 mill.

  2. Nếu bạn muốn tách nó ra, đừng làm theo cách bạn mô tả, hãy tạo một bảng cho các bản ghi mở nhưng không đóng mà bạn sử dụng trước bảng hiện tại của mình. Sau đó, khi một cái gì đó "cập nhật" xóa nó khỏi bảng phân tầng đó và chèn nó vào bảng lớn của bạn. Sử dụng bảng phân tầng theo cách này được coi là cách thực hành hàng đầu / tốt nhất - có một bảng tùy ý chia làm hai luôn là một cơn ác mộng khi làm việc với


Cảm ơn bạn đã dành thời gian trả lời. Hãy tha thứ cho tôi, như trước đây khi tôi nói "Tôi không phải là chuyên gia SQL", tôi nên làm rõ và nói "Tôi thỉnh thoảng sử dụng SQL và thật lòng tôi không chắc là tôi đã đi xa như thế nào". Tôi không quen với khái niệm chỉ số. Trong việc tìm kiếm trên Internet trước khi đăng, thông tin trả về là khá lớn. Bạn có một bài viết mà bạn có thể chỉ cho tôi để mô tả việc lập chỉ mục và làm thế nào để thêm nó vào một bảng / cơ sở dữ liệu hiện có không? EDIT: Tôi đã đi qua từng trường trong bảng và lưu ý rằng "Có thể lập chỉ mục" được đặt thành "Có". Có phải đó là thứ bạn tìm?

2

Tôi nghĩ rằng một chỉ số được lọc sẽ phù hợp với hóa đơn khá độc đáo. Dựa trên nhận xét của bạn cho các câu trả lời khác, có vẻ như một tuyên bố chỉ mục tạo mẫu sẽ hữu ích cho bạn. Câu lệnh tạo chỉ mục sẽ trông giống như:

CREATE NONCLUSTERED INDEX <index name> ON 
   <schema>.tb_applicationusage(f_application, f_computername, f_starttime) INCLUDE (f_ID)
   WHERE f_endtime IS NULL;

Sẽ thật tuyệt nếu bạn có thể đặt ra một UNIQUEràng buộc đối với chỉ mục đó nhưng tôi nghi ngờ bạn sẽ có thể thoát khỏi điều đó bởi vì điều gì đó luôn luôn xảy ra sẽ ngăn chặn việc đăng xuất / tắt ứng dụng thông thường. Tất nhiên, bạn nên thay thế <index name>bằng một tên thích hợp và <schema>với lược đồ của bảng (có thể dbo). Tôi chỉ thêm INCLUDEcâu lệnh vì nó nằm trong truy vấn mẫu của bạn. Nếu bạn thấy rằng bạn không cần điều đó thì cứ thoải mái bỏ nó đi.

Tuyên bố cập nhật của bạn vì nó được viết không phải là một bản cập nhật mà là một lựa chọn. Dưới đây là một mẫu của truy vấn đầy đủ được viết dưới dạng cập nhật:

WITH LastLogin_CTE AS 
(
  SELECT TOP 1
    * -- Generally avoid * notation but I used it here because we're just driving an update
  FROM tb_applicationusage 
  WHERE 
    f_application = @ApplicationName -- Parameterize the name
    AND 
    f_computername = @ComputerName -- Parameterize the name 
    AND 
    f_endtime IS NULL 
  ORDER BY
    f_starttime DESC
)
UPDATE LastLogin_CTE
SET
  f_endtime = SYSUTCDATETIME();

Bản cập nhật này tất nhiên sẽ để lại các hàng mồ côi không bao giờ được đăng xuất. Tôi đoán đó là những gì báo cáo hàng tháng được thiết kế để phát hiện.


Chia tay suy nghĩ:

  • Có lẽ bạn nên tránh tb_, f_và tiền tố khác nếu có thể. Họ chỉ thêm tiếng ồn vào tên đối tượng của bạn khiến nó khó đọc hơn và dường như không phải là thông lệ tốt nhất trong ngành.
  • Về các vấn đề hiệu suất, bạn thực sự nên bao gồm một kế hoạch truy vấn trong câu hỏi của bạn. Điều đó sẽ giúp chúng tôi phát hiện ra các chỉ mục bị thiếu và cung cấp thêm thông tin hữu ích.
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.