Tôi hiện đang được giao nhiệm vụ triển khai một lược đồ lưu trữ cho một lượng dữ liệu tương đối lớn. Dữ liệu chủ yếu sẽ được truy cập để xác định data point
giá trị hiện tại , nhưng tôi cũng được yêu cầu theo dõi sáu tháng lịch sử để theo xu hướng / phân tích dữ liệu.
Một yêu cầu gần đây đã được thêm vào để theo dõi min
/ max
/ sum
giá trị trong một giờ qua.
LƯU Ý: Lý tưởng nhất là tôi muốn xem xét tùy chọn MongoDB, nhưng trước tiên tôi cần chứng minh rằng tôi đã sử dụng hết các tùy chọn SQL-Server.
Dữ liệu
Bảng sau đây biểu thị nguồn dữ liệu chính (được truy vấn thường xuyên nhất). Bảng sẽ có khoảng năm triệu hàng. Các thay đổi dữ liệu sẽ chủ yếu là các UPDATE
câu lệnh với các câu lệnh rất thường xuyên INSERT
sau khi tải dữ liệu ban đầu. Tôi đã chọn phân cụm dữ liệu bởi dataPointId
vì bạn sẽ luôn luôn chọn all values for a given data point
.
// Simplified Table
CREATE TABLE [dbo].[DataPointValue](
[dataPointId] [int] NOT NULL,
[valueId] [int] NOT NULL,
[timestamp] [datetime] NOT NULL,
[minimum] [decimal](18, 0) NOT NULL,
[hourMinimum] [decimal](18, 0) NOT NULL,
[current] [decimal](18, 0) NOT NULL,
[currentTrend] [decimal](18, 0) NOT NULL,
[hourMaximum] [decimal](18, 0) NOT NULL,
[maximum] [decimal](18, 0) NOT NULL
CONSTRAINT [PK_MeterDataPointValue] PRIMARY KEY CLUSTERED ([dataPointId],[valueId])
)
Bảng thứ hai lớn hơn đáng kể với khoảng 3,1 tỷ hàng (đại diện cho sáu tháng qua của dữ liệu). Dữ liệu cũ hơn sáu tháng sẽ bị thanh trừng; mặt khác, INSERT
báo cáo dữ liệu nghiêm ngặt (~ 200 hàng / giây, 720.000 hàng / giờ, 17 triệu hàng / tuần).
// Simplified Table
CREATE TABLE [dbo].[DataPointValueHistory](
[dataPointId] [int] NOT NULL,
[valueId] [int] NOT NULL,
[timestamp] [datetime] NOT NULL,
[value] [decimal](18, 0) NOT NULL,
[delta] [decimal](18, 0) NOT NULL
CONSTRAINT [PK_MeterDataPointHistory] PRIMARY KEY CLUSTERED ([dataPointId], [valueId], [timestamp])
)
Kỳ vọng là bảng này sẽ tăng gấp đôi kích thước khi số lượng giá trị điểm dữ liệu được theo dõi tăng lên 400 hàng / giây (vì vậy đạt ~ 10 tỷ không phải là vấn đề).
(Các) Câu hỏi ( vâng, tôi đang hỏi nhiều hơn một ... chúng đều liên quan chặt chẽ với nhau).
Tôi hiện đang sử dụng cơ sở dữ liệu Phiên bản tiêu chuẩn SQL-Server 2008 R2. Tôi có thể sẽ thực hiện trường hợp nâng cấp lên Phiên bản doanh nghiệp nếu có thể đạt được mức hiệu suất mong muốn với các phân vùng bảng (hoặc MongoDB nếu không thể đạt các mức hiệu suất được yêu cầu với SQL-Server). Tôi muốn đầu vào của bạn về sau:
1) Cho rằng tôi cần tính toán min
, max
và sum
trong một giờ qua (như trong now - 60 minutes
). Cách tiếp cận tốt nhất để theo dõi dữ liệu gần đây là gì:
Giữ dữ liệu gần đây trong bộ nhớ của dịch vụ dữ liệu. Viết ra tính toán tối thiểu / tối đa / trung bình với mỗi dữ liệu CẬP NHẬT.
Truy vấn lịch sử gần đây từ bảng lịch sử (tác động đến câu hỏi tiếp theo?) Trong mỗi câu lệnh CẬP NHẬT. Truy vấn sẽ truy cập dữ liệu mới nhất cho giá trị điểm dữ liệu và chỉ nên quét qua hàng triệu bản ghi gần nhất?
Lưu trữ lịch sử gần đây trong hàng DataPointValue để tránh tra cứu bảng lịch sử? Có lẽ được lưu trữ dưới dạng một chuỗi phân tách và được xử lý bên trong CẬP NHẬT?
Lựa chọn khác tôi chưa xem xét?
2) Đối với DataPointValueHistory
, các truy vấn đối với dữ liệu sẽ luôn luôn bằng dataPointId
và một hoặc nhiều valueId
. Dữ liệu được truy vấn thường sẽ là cho ngày, tuần hoặc tháng cuối cùng, nhưng có thể là trong sáu tháng đầy đủ trong một số trường hợp.
Tôi hiện đang tạo một tập dữ liệu mẫu để thử nghiệm xem liệu có hợp lý hơn khi phân cụm theo dataPointId / valueId / timeStamp hoặc timeStamp / dataPointId / valueId. Nếu bất cứ ai có kinh nghiệm đối phó với một bảng có kích thước này và sẵn sàng cung cấp cái nhìn sâu sắc của họ, nó sẽ được đánh giá cao. Tôi nghiêng về tùy chọn thứ hai để tránh phân mảnh chỉ mục, nhưng hiệu năng truy vấn là rất quan trọng.
Phân cụm
DataPointValueHistory
theo dataPointId -> valueId -> timeStampPhân cụm
DataPointValueHistory
theo timeStamp -> dataPointId -> valueId
3) Cuối cùng, như đã đề cập ở trên, tôi nghĩ sẽ có ý nghĩa khi phân vùng DataPointValueHistory
bảng. Bất kỳ đề xuất nào về cách phân vùng tốt nhất dữ liệu lịch sử sẽ được đánh giá rất cao.
Nếu được phân cụm theo dấu thời gian trước tiên, tôi nghĩ rằng dữ liệu nên được phân vùng theo tuần (tổng cộng 27 phân vùng). Phân vùng cũ nhất sẽ bị thanh trừng sau tuần 27.
Nếu được phân cụm bởi dataPointId trước tiên, tôi nghĩ rằng dữ liệu nên được phân vùng bởi một số mô-đun của id?
Vì tôi có kinh nghiệm rất hạn chế với phân vùng bảng, nên chuyên môn của bạn sẽ được đánh giá cao.