1

레일즈 애플리케이션에는 사용자 데이터가 들어있는 다양한 데이터베이스 테이블이 있습니다. 이 테이블 중 일부는 많은 행을 가지며 (경우에 따라 사용자 당 500,000 행까지) 자주 질의됩니다. 어떤 테이블이라도 쿼리 할 때마다 현재 사용자의 user_id는 쿼리의 어딘가에 있습니다. 테이블과 사용자가 직접 관계가 있거나 직접 다른 테이블을 통해 관련이있는 경우 조인을 통해 테이블에 연결됩니다.user_ids를 정규화하거나 정규화하지 않기 위해서

더 빠른 성능을 위해 user_id를 비정규 화하여 모든 테이블에 포함시켜야합니까? 그래서,

  • 주소가 사용자에 속하고,
  • 봉투 사용자에 속하는 USER_ID을 가지고 있으며,
  • AddressesEnvelopes는 주소와 봉투를 연결하는 USER_ID 있습니다


    여기에 하나의 예입니다 그것은 envelope_id와 address_id를 가지고 있습니다 - 그것은 user_id가 없지만 봉투 나 주소 (동일한 사용자에 속해야 함)를 통해 접근 할 수 있습니다.

하나 개의 일반적인 고가의 쿼리는 내가 그 테이블에서 아무것도 필요하지 않더라도, 주소 또는 봉투 중 하나와 결합하여 수행 할 수있는 특정 사용자에 대한 모든 AddressesEnvelopes을 선택하는 것입니다. 아니면이 테이블에 사용자 ID를 복제 할 수 있습니다. 여기


다른 시나리오입니다 :

  • 편지 사용자에 속하고,
  • 수령인이 편지에 속하는 USER_ID을 가지고 있으며,
  • RecepientOption가 수령인에 속하는 letter_id을 가지고 있으며,이 있습니다 recepient_id

수신자와 수신자 모두에서 user_id를 복제하는 것이 합리적일까요? 비록 내가 항상 편지를 통해 협회를 통해 올라갈 수있는 옵션을?


일부 노트 :

  • 는 사용자간에 공유되는 물건이 결코 없습니다. 관련 개체의 전체 은 항상 은 (는) 같은 사용자에게 속합니다.
  • 개체의 사용자 소유자가 변경되지 않습니다.
  • 데이터 집약적 인 응용 프로그램이기 때문에 데이터베이스 성능이 중요합니다. 많은 쿼리와 많은 테이블이 있습니다. 인덱스를 만들 때

그래서 모든 테이블에 user_id를 포함해야한다 그래서 그것을 사용할 수 있습니까? 아니면 나쁜 디자인일까요?

답변

2

복합 기본 키로 작업하려는 경우 비정규화할 필요가 없음을 지적하고 싶습니다. AddressEnvelop 케이스 샘플 : 나는 그것을 피하지만, 사실을 고려할 수있는 경우

user(
    #user_id 
) 
address(
    #user_id 
, #addres_num 
) 
envelope(
    #user_id 
, #envelope_num 
) 
address_envelope(
    #user_id 
, #addres_num 
, #envelope_num 
) 

합니다 (# 기본 키 열을 나타냅니다)

나는 당신이 말하는 것을이 디자인의 팬이 아니에요 모든 오브젝트 그 이 유형의 디자인은 비교적 간단하게 데이터를 분할 (논리적으로 사용자의 범위를 여러 테이블이나 물리적으로 여러 데이터베이스 또는 컴퓨터를 사용하여 여러 데이터베이스 또는 컴퓨터를 사용하여 배치) 할 수 있습니다.

이 유형의 디자인에서는 클러스터 된 인덱스를 사용한다 (MySQL에서는 InnoDB 테이블의 기본 키가 clu stered 인덱스). user_id가 항상 인덱스의 첫 번째 열임을 보장하면 각 테이블에 대해 한 사용자의 모든 데이터가 디스크에 가까이 저장됩니다. 이것은 항상 user_id로 쿼리 할 때 좋습니다. 그러나 다른 객체로 쿼리하면 퍼포먼스가 손상 될 수 있습니다 (이 경우 중복 된 것이 더 나은 해결책 일 수 있습니다)

어쨌든 디자인을 변경하기 전에 먼저 스키마가 이미 최적화되어 있고 외래 키 열에 적절한 인덱스가 있는지 확인하십시오. 성능이 가장 중요한 경우, 여러 솔루션을 시도하고 벤치 마크를 수행해야합니다.

+0

고마워, 롤랜드. 그게 정확히 내가하고 싶은 생각이야.아마도 나는 사용자 테이블 내에서 다른 테이블로 데이터를 역 정규화하지 않기 때문에 사용하는 잘못된 단어입니다. user_id를 다른 키를 통해 user_id에서 가져올 수있는 테이블의 키로 포함하는 것만으로 (예 : 주소 또는 봉투를 통해 user_id를 얻을 수있는 address_envelopes 예제). 클러스터 된 인덱싱 및 사용자 별 테이블/머신 간 데이터 파티셔닝은 훌륭한 아이디어입니다! –

1

만큼 당신

A)

B)는 데이터베이스의 일부가 실제 정규화 된 데이터이며, 중복 개선이

이있는 알 측정 가능한 성능 향상을 얻을 그것을하지 않을 이유가 없다!

+0

쿨! 좋은 점은 그다지 이상하지 않다는 것입니다. 감사. –

1

실제로 측정 성능 이 있습니까? 500 000 행은 매우 큰 테이블되지 않습니다. 매우 복잡하지 않고 열에 적절한 색인이 있으면 선택 항목이 신속하게 합리적이어야합니다.

나는 느린 쿼리가 있는지 먼저 확인하고 인덱스를 사용하여 인덱스를 최적화하려고합니다. 그것이 충분하지 않다면, 나는 단지 비정규 화를 들여다 볼 것이다.

다른 방법으로 필요한 성능을 얻을 수 없다면 합리적인 것처럼 보이는 비정규 화가 발생합니다. 비정규 화 된 필드를 최신으로 유지하십시오.

+0

그 두 번째. 500,000은 그리 많지 않습니다. 얼마나 빨리해야하는지, 그리고 어떤 양의 실적 향상을 원한다고 생각하십니까? –

+0

참고로 총 500,000 레코드가 아니라 사용자 당 500,000 레코드입니다. 동시 사용자가 훨씬 적을지라도 (총 1 % 미만) 총 사용자 수는 크기 조정 문제없이 10 만개 이상으로 증가 할 수 있어야합니다. 따라서 사용자 당 100,000 명의 활성 사용자와 500,000 개의 레코드로 50000000000 개의 레코드가 생성됩니다. 이것이 내가 user_id로 파티션하는 것이 결국 도움이 될 수 있다고 생각하는 이유입니다. 측정 된 성능 문제는 아직 없습니다. user_id로 모든 테이블을 분할하고 각 복합 인덱스의 첫 번째 항목으로 사용하는 것이 좋을지는 모르겠다. –