나는 현재 비교적 많은 양의 데이터에 대한 스토리지 스키마 구현을 맡고 있습니다. 데이터는 주로 현재 data point
값 을 결정하기 위해 액세스 되지만 데이터 추세 / 분석에 대한 지난 6 개월의 기록을 추적해야합니다.
지난 1 시간 동안 의 min
/ max
/ sum
값 을 추적하기 위해 최근 요구 사항이 추가되었습니다 .
참고 : 이상적으로는 MongoDB 옵션을 고려하고 싶지만 SQL-Server 옵션을 먼저 사용했음을 증명해야합니다.
자료
다음 표는 기본 데이터 소스 (가장 자주 쿼리 됨)를 나타냅니다. 테이블에는 약 5 백만 개의 행이 있습니다. 데이터 변경은 주로 초기 데이터로드 후 UPDATE
매우 가끔씩 표시되는 INSERT
명령문입니다. 나는 dataPointId
당신이 항상 선택할 것이므로 데이터를 클러스터링하기로 결정했다 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])
)
두 번째 테이블은 약 31 억 행 (지난 6 개월 동안의 데이터를 나타냄)으로 현저히 큽니다. 6 개월이 지난 데이터는 제거됩니다. 그렇지 않으면 엄격하게 데이터 INSERT
문 (~ 200 행 / 초, 720,000 행 / 시간, 1,700 만행 / 주)입니다.
// 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])
)
추적 된 데이터 포인트 값의 수가 400 행 / 초로 증가함에 따라이 테이블의 크기가 두 배가 될 것으로 예상됩니다 (약 100 억에 도달하는 것은 문제가되지 않습니다).
The Question (s) (예, 하나 이상을 요청하고 있습니다. 모두 밀접하게 관련되어 있습니다).
현재 SQL-Server 2008 R2 Standard Edition 데이터베이스를 사용하고 있습니다. 테이블 파티션으로 원하는 성능 수준을 얻을 수 있다면 (또는 SQL-Server로 필요한 성능 수준에 도달 할 수없는 경우 MongoDB) Enterprise Edition으로 업그레이드 할 수 있습니다. 다음에 대한 귀하의 의견을 부탁드립니다.
1) min
, max
및 sum
지난 1 시간 동안 ( now - 60 minutes
) 을 계산해야한다고 가정합니다 . 최근 데이터를 추적하는 가장 좋은 방법은 무엇입니까?
최근 데이터를 데이터 서비스의 메모리에 보관하십시오. 각 데이터 UPDATE로 계산 된 최소 / 최대 / 평균을 씁니다.
각 UPDATE 문 동안 히스토리 테이블에서 최근 히스토리를 조회하십시오 (다음 질문에 영향을 미칩니 까?). 쿼리는 데이터 포인트 값에 대한 최신 데이터에 액세스하고 지난 백만 레코드 정도만 스캔해야합니까?
히스토리 테이블 조회를 피하기 위해 최근 히스토리를 DataPointValue 행에 저장 하시겠습니까? 아마도 구분 된 문자열로 저장되어 UPDATE proc 내부에서 처리됩니까?
고려하지 않은 다른 옵션은 무엇입니까?
2)의 경우 DataPointValueHistory
, datable에 대한 쿼리는 항상 dataPointId
하나 이상의 쿼리 valueId
입니다. 쿼리 된 데이터는 일반적으로 마지막 날, 주 또는 월에 대한 것이지만 경우에 따라 전체 6 개월에 대한 것일 수도 있습니다.
현재 dataPointId / valueId / timeStamp 또는 timeStamp / dataPointId / valueId로 클러스터링하는 것이 더 적합한 지 실험하기 위해 샘플 데이터 세트를 생성 중입니다. 누구 든지이 크기의 테이블을 다루는 데 경험이 있고 통찰력을 기꺼이 제공하려는 경우 감사하겠습니다. 인덱스 조각화를 피하기 위해 후자의 옵션에 기울고 있지만 쿼리 성능이 중요합니다.
DataPointValueHistory
dataPointId-> valueId-> timeStamp 별 클러스터시간
DataPointValueHistory
소인 별 클러스터 -> dataPointId-> valueId
3) 마지막으로 위에서 언급했듯이 DataPointValueHistory
테이블 을 분할하는 것이 합리적이라고 생각 합니다. 히스토리 데이터를 가장 잘 분할하는 방법에 대한 제안은 크게 감사하겠습니다.
타임 스탬프로 먼저 클러스터 된 경우 데이터를 주별로 분할해야한다고 생각합니다 (총 27 개의 파티션). 가장 오래된 파티션은 27 주 후에 제거됩니다.
dataPointId로 먼저 클러스터링 된 경우 데이터를 일부 모듈러스로 분할해야한다고 생각합니까?
테이블 파티셔닝에 대한 경험이 매우 제한적이기 때문에 귀하의 전문 지식에 감사드립니다.