다음 중 어떤 테이블 디자인이 성능에 더 좋습니까? 이 테이블은 빠르게

계정에서 수집하는 일일 비용을 추적하는 무언가를 작성하라는 요청을 받았으며이를 지원하는 데이터베이스 테이블 스키마를 알아 내려고 노력 중입니다.

내가 아는 것은 다음과 같습니다

  • 회사는 250 만 개가 넘는 계정을 보유하고 있습니다.
  • 이 중 현재 월 평균 200,000 명의 직원이 근무하고 있습니다 (현재 직원 수에 따라 변경됨).
  • 그들은 추적하고 싶은 13 가지의 다른 비용 유형을 가지고 있으며, 앞으로 더 많은 것을 추가 할 것이라고 경고했습니다.
  • 그들은 매일 비용을 추적하기를 원합니다
  • 비용은 전체 재고에 분할되지 않습니다. 월 단위로 작동하는 계정 수 (200,000)로 분할되거나 사용자가 계정 식별자를 입력하여 계정 그룹에 비용을 적용하거나 단순히 비용을 적용 할 계정을 지정할 수 있습니다.

내 첫 번째 생각은 표준화 된 데이터베이스였습니다.

계정 ID
데이트
CostTypeId
양

이것에 대한 나의 문제는 수학을하는 것입니다. 이 테이블은 빠르게 커질 것입니다. 현재 한 달 동안 모든 13 개의 비용 유형이 모든 작업 계정에 적용된다고 가정하면 200k * 13 * N days in month, 이는 한 달에 약 7 천 8 백만에서 8 천만 건에 달하거나 매년 10 억 건에 가까운 레코드입니다.

내 두 번째 생각은 그것을 비정규 화하는 것이 었습니다

계정 ID
데이트
총비용
비용 유형 1
비용 유형 2
비용 유형 3
비용 유형 4
비용 유형 5
비용 유형 6
비용 유형 7
비용 유형 8
비용 유형 9
비용 유형 10
비용 유형 11
비용 유형 12
비용 유형 13

이 방법은 비정규 화 된 방식으로 한 달에 최대 6 백만 건 ( 200k * N days in month) 또는 연간 약 72 백만 건을 생성 할 수 있습니다 . 첫 번째 방법보다 훨씬 적지 만 향후 회사에서 새로운 비용 유형을 결정하는 경우 다른 데이터베이스 열을 추가해야합니다.

두 가지 방법 중 어느 것을 선호합니까? 왜? 더 잘 처리 할 수있는 다른 대안이 있습니까?

서머 닝 보고서와 상세 보고서 모두 성능보고에 가장 관심이 있습니다. 계정에 비용을 분산시키는 작업은 아무도 없을 때 밤마다 실행됩니다. 두 번째 관심사는 데이터베이스 크기입니다. 기존 데이터베이스는 이미 거의 300GB이며 디스크의 공간은 약 500GB라고 생각합니다.

데이터베이스는 SQL Server 2005입니다



답변

연간 10 억 레코드는 많지 않습니다.

파티셔닝 (비용 유형별) 및 아카이빙을 통해 관리가 가능합니다.

저장할 데이터 항목의 수는 여전히 200k * 13 * N입니다. 열의 경우 페이지 당 행 수가 줄어들고 행보다 공간이 더 많이 사용됩니다. “CostType1″이 고정 길이 데이터 유형이 아니지만 한계가있는 경우 얻을 수 있습니다.

그들이 말하는 “키스”


답변

디자인이 밤이나 낮의 차이를 만들 수는 있지만이 경우 필 요에 따라 인덱스를 포함하여 인덱스에 더 중점을 둡니다. 또한 테이블 파티셔닝과 같은 매우 큰 테이블을 처리하기 위해 SQL Server가 제공하는 몇 가지 도구를 살펴 보겠습니다.

테이블에 800 억 개의 레코드가 있지만 적절한 인덱싱을 통해 특정 지점에서 실제로 관심이있는 레코드는 물리적으로 디스크에 그룹화됩니다. SQL Server에서 데이터가 구성되는 방식으로 인해 인덱스 경계로 분할 된 데이터는 전체 테이블을 읽을 필요가 없기 때문에 다른 테이블에도있을 수 있습니다.

테이블을 분할하도록 선택하면 액세스 시간과 삽입 시간을 향상시킬 수 있습니다.


답변

나는 정상화 할 것입니다. 우리는 은행에서 고객 계정 수익성에 대한 비용 회계를 수행했으며, 비용 센터 나 총계정 원장 또는 매월 수백만 개의 계정에 대한 다양한 기타 기술에 의해 할당 된 수백 개의 드라이버를 사용하여 250m 이상의 개별 비용을 생성했습니다.

예를 들어 ATM의 총 서비스 비용은 상대적인 사용량에 따라 ATM을 사용한 계정으로 나뉩니다. 따라서 1 백만 달러가 ATM 서비스에 쓰이고 5 명의 고객 만이 각각 한 번만 사용하고 한 고객은 5 번 사용한 경우, 한 고객은 $ .5m, 다른 고객은 각각 $ 1.1m을 지불했습니다. 다른 드라이버는 훨씬 더 복잡 할 수 있습니다.

궁극적으로, 특정 소스 / 드라이버로부터 비용을받지 않는 일부 계정과 아무것도 얻지 못하는 일부 계정은 드물게 발견 될 것입니다. 정규화 된 모델에는 해당 행이 없습니다. 비정규 화 된 모델에서 일부 빈 열이있는 행이 존재합니다. 또한 희소 정규화 된 모델에서는 특정 “버킷”에서 NULL이 아닌 모든 행을 검사하는 것보다 행의 존재가 일반적으로 확인하는 것이 더 빠르기 때문에 (비용 유형의 커버링 인덱스를 사용하여) 성능이 향상되어야합니다. 모든 금액 열의 색인-매우 낭비되기 시작하는 것을 볼 수 있습니다).


답변

성능 이점에 관계없이 옵션 1을 선호합니다. 옵션 2는 베드로에게 폴을 지불하기 위해 강탈 할 것이라고 생각합니다.


답변

옵션 1을 사용하고보고 속도가 문제가되는 경우 표 2를 추가하고 일종의 자동화 된 야간 / 오프 피크 프로세스로보고 데이터베이스에 채 웁니다.

그런 다음 필요에 따라 일일 테이블 -2 구조를 추가로 매주, 매월, 분기 별, 매년 롤업으로 롤업 할 수도 있습니다.

그러나 내가 말했듯이 ‘원시’데이터를 적절한 (정규화 된) 형식으로 저장하기로 선택했습니다.


답변

언급 한 볼륨을 고려할 때 TotalCost가없는 두 번째 옵션을 사용합니다. 당신은 여전히 ​​정상화되어 있다고 말할 수 있습니다.


편집 : 대안으로, 요구 사항과 AccountId의 크기에 따라 다음을 고려할 수도 있습니다.

AccountDate
-----------
AccountId
Date
AcDtID (surrogate key)

Costs
-------
AcDtID
CostTypeId
Amount  

이 디자인을 사용하면 비정규 화 된 TotalCost를 첫 번째 테이블에 추가하고 야간에 다시 계산하여 첫 번째 테이블에서만 일부 보고서를 실행할 수 있습니다.


답변

하위 쿼리를 사용하고 두 번째 행을 열 또는 여러 열로 선택할 수 있도록 실제로 firs 테이블을 두 개의 테이블로 나눕니다. 그렇게하면 더 유연 해져서 두 번째 것과 같은 결과를 더 쉽게 얻을 수 있습니다.