이 질문의 환경은 AWS RDS의 PostgreSQL 9.6.5입니다.인덱싱 된 비트 세트에 대한 대용량 대량 업데이트를위한 최적 접근 방식
문제는 다음과 같은 논리적 데이터 모델을 포함하는 3 억 개 행이 테이블에 대한 최적의 스키마 설계 및 배치 업데이트 전략에 관한 것입니다 :
id
을code
:year
정수 999 : 정수 년- 플래그 : 변수 번호 (1000)의 이름과 관련된 각각의 새로운 플래그는 시간이 지남에 추가. 이상적으로, 깃발은 (
null
), (true
/1
) 및 off (false
/0
)의 세 값을 가진 것으로 생각해야합니다. 추가 업데이트 (아래 참조)를 사용하면 플래그를 간단한 비트 (on 또는 off, no absent)로 처리 할 수 있습니다. "On"값은 일반적으로 매우 희박합니다 : < 1/1000.
쿼리는 일반적으로 code
때때로 또한 참여 year
와 (이름으로) 하나 개 이상의 플래그의 존재 여부에 대한 부울 표현식을 포함한다.
데이터는 Apache Spark를 통해 일괄 적으로 업데이트됩니다. 즉, 업데이트는 플랫 파일 (예 : COPY 형식 또는 SQL 작업)로 표시 될 수 있습니다. 한 번에 하나의 업데이트 만 활성화됩니다. code
및 year
에 대한 업데이트는 매우 드뭅니다. 플래그를 업데이트하면 업데이트 당 행 수가 1 ~ 5 % (3 ~ 15 백만 행)에 영향을줍니다. 업데이트 행에는 모든 플래그와 해당 값, 업데이트 될 "on"플래그 또는 값이 변경된 플래그 만 포함될 수 있습니다. 전자의 경우, Spark는 플래그의 현재 값을 얻기 위해 데이터를 쿼리해야합니다.
업데이트하는 동안 작은 읽기로드가 발생합니다.
질문은 설명 된대로 & 쿼리를 지원하는 최적의 스키마 및 관련 업데이트 전략에 대한 것입니다. 지금까지 연구에서
일부 댓글 : 1,000 인덱스를 요구, 일부 DDL의 복잡성뿐만 아니라, 매우 효율적인 행 표현을 만들 수 있지만 것입니다 1,000 부울 열을 사용
.
개별 비트를 인덱싱 할 수있는 방법이 있다면 비트 문자열이 좋습니다. 또한, 그들은 결석 한 깃발을 나타내는 좋은 방법을 제공하지 않습니다. 이 접근법을 사용하려면 플래그 이름과 비트 ID 사이에 룩업 테이블을 유지해야합니다. 그러나 병합 업데이트는
||
으로 작동하지만 PostgreSQL의 MVCC에서는 전체 행을 대체하는 대신 플래그를 업데이트하는 것이별로 도움이되지 않습니다.JSONB 필드는 색인 생성을 제공합니다. 그것들은 또한
null
표현을 제공하지만, 비용이 발생합니다 : "off"인 모든 플래그는 명시 적으로 설정되어야하며 이는 필드를 상당히 크게 만듭니다.null
표현을 무시하면 JSONB 필드는 비교적 작습니다. 추가 축소를 위해 조회 테이블에 짧은 1-3 자 필드 이름을 사용할 수 있습니다. 같은 코멘트가 비트 문자열처럼 병합됩니다.tsvector
/tsquery
:이 데이터 유형에는 경험이 없지만 이론적으로 이름별로 "on"플래그 세트를 정확하게 표현한 것 같습니다. 형태소 분석으로 인한 충돌이 없는지 확인하기 위해 추가 요구 사항이있는 플래그 테이블 이름을 토큰에 매핑하는 조회 테이블을 사용해야합니다.
이 작업을 수행하는 데 필요한 성능상의 이유가 있음을 추가해야합니다. 큰 행의 업데이트가 느립니다. – AlexanderMP
1 인당 1000 개 이상의 플래그가있을 때마다 매회 9 ~ 45 억 개의 행이 업데이트되어 3 천억 행의 테이블을 제안 하시겠습니까? 즉, "켜기"로 설정된 플래그 만 유지하려는 경우 값 열을 사용하는 이유는 무엇입니까? 하나의 큰 행을 업데이트하는 것보다 빠르게 1,000 개의 작은 행을 업데이트 할 것으로 기대하십니까? – Sim
또한, 나는'A 또는 (B와 C) 플래그가 아닌 (D와 E)'플래그에 대한 쿼리가 스키마와 어떤 관계가 있는지 궁금합니다. 플래그 정보를 여러 행으로 분할하면 동일한 계정에 대한 플래그 종속성을 평가하는 추가 작업이 필요합니다. – Sim