7

Chúng tôi có một cơ sở dữ liệu rất lớn WriteDB, lưu trữ dữ liệu giao dịch thô và chúng tôi sử dụng bảng này để ghi nhanh. Sau đó, với các kịch bản sql tôi nhập dữ liệu từ WriteDB vào ReadDB trong cùng một bảng tương tự, nhưng mở rộng với một số giá trị bổ sung + quan hệ được thêm vào. Nhập tập lệnh giống như sau:INSERT INTO đi chậm hơn nhiều so với thời gian trong SQL Server 2012

TRUNCATE TABLE [ReadDB].[dbo].[Price] 
GO 
INSERT INTO [ReadDB].[dbo].[Price] 
SELECT a.*, 0 as ValueUSD, 0 as ValueEUR 
from [WriteDB].[dbo].[Price] a 
JOIN [ReadDB].[dbo].[Companies] b ON a.QuoteId = b.QuoteID 

Vì vậy, ban đầu có khoảng 130 triệu. các hàng trong bảng này (~ 50GB). Mỗi ngày một số người trong số họ thêm vào, một số người trong số họ thay đổi, vì vậy ngay bây giờ chúng tôi quyết định không phức tạp hơn logic và chỉ cần nhập lại tất cả dữ liệu. Vấn đề là vì một số lý do với thời gian tập lệnh này hoạt động lâu hơn và lâu hơn, trên cùng một lượng dữ liệu. Lần chạy đầu tiên mất ~ 1h, bây giờ nó đã được chụp 3h

Máy chủ SQL sau khi nhập không hoạt động tốt. Sau khi nhập (hoặc trong khi nó) nếu tôi cố gắng chạy các truy vấn khác nhau, thậm chí đơn giản nhất chúng thường không thành công với các lỗi hết thời gian chờ.

Lý do của hành vi xấu như thế nào và cách khắc phục điều này?

+3

Có hai phần này - INSERT và SELECT. Tìm ra cái nào bằng cách chạy lệnh SELECT. –

+0

Máy chủ có bao nhiêu bộ nhớ? Nó có thể là bộ làm việc vượt quá bộ nhớ dần dần theo thời gian. – usr

+0

@usr Máy chủ có ram 64GB, 55GB được gửi đến máy chủ SQL. Tất cả bộ nhớ có sẵn do MS SQL tiêu thụ. Loại đĩa - HDD tôi nghĩ. Nhưng cấu hình máy chủ không thay đổi theo thời gian - vì vậy tôi không thể hiểu được sự xuống cấp hiệu suất này. – Ph0en1x

Trả lời

5

Một giả thuyết là tập dữ liệu 50GB đầu tiên của bạn đã lấp đầy bộ nhớ có sẵn để lưu vào bộ nhớ cache. Khi cắt bớt bảng, bộ nhớ cache của bạn giờ đây trống rỗng. Hành vi xen kẽ này làm cho việc sử dụng bộ nhớ cache trở nên khó khăn và gây ra một số lượng đáng kể bộ nhớ cache bị mất/tăng thời gian IO.

Hãy xem xét các chuỗi sự kiện sau:

  1. Bạn tải dữ liệu ban đầu của bạn vào WriteDb. Trong quá trình tải, các trang trong WriteDb được lưu trữ. Có rất ít tranh cãi về bộ nhớ vì chỉ có một bản sao của tập dữ liệu và đủ bộ nhớ.
  2. Ban đầu bạn điền vào ReadDb. Các trang cần thiết để điền vào ReadDb (dữ liệu trong WriteDb) đã được lưu trữ phần lớn. Ít lần đọc được yêu cầu từ đĩa, và thời gian IO của bạn có thể được dành riêng để ghi dữ liệu được chèn vào cho ReadDb. (Đây là lần chạy nhanh đầu tiên của bạn.)
  3. Bạn tải tập dữ liệu thứ hai của mình vào WriteDb. Trong quá trình tải, không có đủ bộ nhớ để lưu trữ cả hai dữ liệu hiện có trong ReadDb và dữ liệu mới được ghi vào WriteDb. Sự tranh cãi về bộ nhớ này dẫn đến ít trang WriteDb được lưu trữ.
  4. Bạn cắt bớt ReadDb. Điều này làm mất hiệu lực một phần đáng kể bộ nhớ cache của bạn (tức là 50GB dữ liệu ReadDb đã được lưu trong bộ nhớ cache).
  5. Sau đó, bạn thử tải lần đọc thứ hai của ReadDb. Ở đây bạn có rất ít WriteDb được lưu trữ, do đó thời gian IO của bạn được chia giữa các trang đọc của WriteDb (truy vấn của bạn) và viết các trang của ReadDb (chèn của bạn). (Đây là lần chạy chậm thứ hai của bạn.)

Bạn có thể kiểm tra lý thuyết này bằng cách so sánh tỷ lệ bỏ qua bộ nhớ cache SQL Server trong hoạt động tải đầu tiên và thứ hai.

Một số cách để cải thiện hiệu suất có thể là để:

  • Sử dụng mảng đĩa riêng biệt cho ReadDb/WriteDb để tăng hiệu suất IO song song.
  • Tăng bộ nhớ cache khả dụng (lượng bộ nhớ máy chủ) để chứa kích thước kết hợp của ReadDb + WriteDb và giảm thiểu bộ nhớ cache bị thiếu.
  • Giảm thiểu tác động của từng hoạt động tải trên các trang đã lưu trong bộ nhớ cache hiện tại bằng cách sử dụng câu lệnh MERGE thay vì bán phá giá/tải 50GB dữ liệu cùng một lúc.
Các vấn đề liên quan