2011-09-07 3 views
1

DB 비정규 화와 관련하여 디자인 문제가 있습니다.
나는 비교적 큰 데이터베이스를 만들고 있으며 가능한 한 많이 최적화해야합니다.mysql 데이터베이스 체인 테이블 비정규 화

다음은 매우 간단한 모델입니다.
그림의 모든 테이블을 체인으로 연결하고 정규화 된 데이터베이스를 사용하여 특정 국가의 모든 사용자를 가져와 모든 테이블에 가입해야합니다. 그것은 cca 250 개국 x cca 12000 개 도시 x cca 625000 개 지역 x? 주소 x? 사용자 ... 간단히 말해서 가입 기간이 길고 시간이 오래 걸립니다.

내가하고 싶은 일은 user 테이블에서 country_id을 중복하여 모든 가입없이 동일한 쿼리를 얻을 수 있습니다.

질문 : 그런 모델에 일관성을 유지하는 가장 좋은 방법은 무엇입니까 (btw. MySql 사용)?

데이터를 삽입/업데이트/삭제할 때 응용 프로그램 수준에서 일관성을 유지하는 것이 가장 빠른 방법입니다.

기타 저장 프로 시저는 실제로 이점이 없습니다. 직접 호출 된 경우에만 일관성을 유지합니다. 프로 시저없이 일부 변경을 수행하려는 경우 일관성이 깨집니다.

나는 또한 트리거를 보았습니다 ... 실제로 구현하는 방법과 성능에서 얼마나 많이 얻을 것인가에 대해서는 잘 모릅니다.

어쨌든 db 수준에서 일관성을 유지하는 것이 좋습니다.

어떤 조언이 필요합니까?

Sample model

답변

0

정말 모든 데이터를 비정규 화하려고하지 않는 가정에 합류 많은 아니에요.

반면에 대부분의 사람들은 주소 테이블을 가지고 있거나 주소 테이블을 사용자 테이블에 보관합니다. 얼마나 많은 국가/도시가 지원을 원하십니까? 얼마나 많은 사용자가 있습니까? 사진에서

+0

내가 말했듯이, 그것은 단순화 된 모델입니다. 이런 종류의 구조가 필요합니다. 기록의 수에 관해서는, 당신은 그렇게 세계의 어느 곳에서나 등록 할 수 있어야합니다. 그래서 게시물의 인물들은 그것을 꽤 많이 소집합니다.예측하기 힘든 사용자 수 ... 어쨌든 수십만 사용자를 처리 할 수 ​​있어야합니다. 또한 많은 쿼리가 국가마다 다르므로 모든 것을 여러 번 추가하기가 너무 어려워 보입니다. – ZolaKt

+0

사용자 테이블에 countryID가 있고 StateID와 a ... 등이 있습니다. 계층 구조가 필요하지 않으면 몇 가지 복잡한 비즈니스 목적, 나는 그것을 피하는 것이 좋습니다. –

+0

좋습니다.하지만 일관성을 보장하는 방법은 실제로 사용하지 않는 모델과 같은 모델이어야합니다. – ZolaKt

4

모든 테이블은 체인 및 표준화 데이터베이스 예를 들어 나는 모든 테이블을 조인해야 특정 국가에서 모든 사용자를 얻을 수 있습니다.

테이블이 "정규화"되어 있지 않기 때문에 대리 키 (ID 번호)를 사용하므로 모든 테이블을 조인해야합니다. ID 번호와 같은 대리 키를 사용하면 정규화와 아무 관련이 없습니다.

자연 키와 외래 키 제약 조건 만 있으면 문제를 해결할 수 있습니다.

어떻게 작동하는지 보는 가장 쉬운 방법은 전체 데이터로 시작하여 완전히 뒤로 작업하는 것입니다. 모든 데이터가 올바른 것으로 가정하십시오.

addr_id street   street_num  region city   country 
-- 
1  Babukiaeeva  3a    10000  Zagreb  Croatia 
2  Riva    16    51000  Rijeka  Croatia 
3  Andrije Hebranga 2-4    10000  Zagreb  Croatia 
4  Andrijeviaeeva 2    110000  Zagreb  Croatia 

는 "도시 국가 '크로아티아'에서 '자그레브'와 관련된 지역 '10000'"와 같은 사실을 기록 새 테이블을 생성하고,이 쿼리에서 그것을 채우려면.

SELECT DISTINCT region, city, country from addresses; 

표는 다음과 같습니다.

Table: regions 
Primary key: {region, city, country} 

region city  country 
-- 
10000 Zagreb Croatia 
51000 Rijeka Croatia 
110000 Zagreb Croatia 

그런 다음 외래 키 참조를 설정하십시오.

ALTER TABLE addresses 
ADD CONSTRAINT FOREIGN KEY  (region, city, country) 
       REFERENCES regions (region, city, country); 

새 테이블을 생성, "도시 '자그레브'국가 '크로아티아'에"와 같은 사실을 기록이 쿼리를 채우려면.

SELECT DISTINCT city, country from regions; 

표는 다음과 같습니다.

Table: cities 
Primary key: {city, country} 

city  country 
-- 
Zagreb Croatia 
Rijeka Croatia 

그런 다음 외래 키 참조를 설정하십시오.

ALTER TABLE regions 
ADD CONSTRAINT FOREIGN KEY  (city, country) 
       REFERENCES cities (city, country); 

국가별로 반복하십시오. 표 국가, 도시 및 지역은 모두 핵심이므로 5NF에 있습니다. (키가 아닌 열이 없으므로 키가 아닌 종속성을 가질 수 없습니다.) 유럽의 모든 지역과 마찬가지로 넓은 영역의 컨텍스트에서 주소 테이블 또한 5NF입니다.

조인이 필요하지 않으므로 쿼리 성능 측면에서 현재 스키마 주위를 울릴 가능성이 있습니다.

ON UPDATE CASCADE; 당신은 이 아니지만,은 계단식 삭제를 원합니다.

+0

이것은 완전한 이중화 접근 방식입니다. performace 이유로 합성 키를 사용하지 않는 것이 좋습니다. 그러나 여전히, 모든 것을/모든 곳에서 복제하기 때문에 이것이 이것을하는 방법이라고 확신하지 않습니다. 최종적으로 구체화 된 뷰 접근 방식을 사용하는 것이 좋지 않다고 생각합니다. – ZolaKt

+0

"중복"은 관계형 이론의 전문 용어입니다. 외래 키를 저장하는 것과 아무런 관련이 없습니다. (외래 키가 필요한 것입니다.) * 이러한 * 복합 키는 모든 조인을 제거합니다. 대부분의 경우 이러한 종류의 스키마는 3 또는 4 조인보다 빠르게 수행됩니다. 나는 200 번 빨리 수행 한 이와 같은 테스트를 실행했습니다. 이 스키마 또는 구체화 된보기로 커밋하기 전에 성능을 테스트해야합니다. –

+0

예, 그들은 조인을 제거합니다. 그렇습니다. 그러나 많은 데이터 (각 테이블의 모든 "하위"키)를 복제하며 선점 문제가 있습니다. Composit 키의 성능은 MySql에서 더 낮기 때문에 새로 증가 된 ID를 intruduce하고 UNIQUE로 구성하는 것이 좋습니다. 그러나, 어쨌든 : 저는 이것에 대해 구체화 된 접근법을 더 좋아합니다. 여전히 지속성 문제가 있지만 "원본"테이블에는 중복성이 없습니다. – ZolaKt

1

우선 - 정말 느린가요? 시도해 보셨습니까? 당신은 모든 사용자를 덤프 (왜?)하는 응용 프로그램을 운영하고 있습니까? 아니면 단 한 명/소수의 사용자를 지금 당장 가져오고 있습니까? 모든 ID에 기본 키가 있기 때문에 검색 속도가 느려서는 안되며 결국 배경에 B 트리가 있습니다.

두 번째로, 나는 거리 숫자 수준으로 표준화하지 않을 것이므로 그로부터 어떤 이점도 거의 얻지 못할 것이므로 사용자와 주소 사이에 거의 1 : 1의 관계가 생길 것입니다. 따라서 거리 번호를 클라이언트로 옮기거나 주소 테이블 전체를 사용자에게 옮길 수도 있습니다. 나는 아마도 지역 테이블을 클라이언트 (이 도시 지역입니까?)로 이동시키고 사용자, 도시 및 국가 테이블로 끝낼 것입니다.

두 개의 조인이 있습니다. 너무 느린 경우 중복 된 국가 키를 입력 할 수 있습니다 (또는 국가 이름이 비정규 화되어 있기 때문에). 트리거을 사용하면 무결성을 유지할 수 있습니다. 삽입 및 업데이트 트리거 (regionId/cityId가 변경된 경우에만 업데이트해야 함) 및 국가에 업데이트 트리거 (국가 이름이 인 경우)를 작성해야합니다. 드문 경우지만 해당 국가의 이름이 변경되는 경우 사용자 테이블이 표시됩니다.

성능상으로는 얻을 수는 없겠지만 트리거가 없어지 겠지만, 사용자 테이블에 삽입 및 업데이트가 자주 발생하지 않는다고 생각합니다.

마지막으로, 당신 (웹?) 응용 프로그램의 성격과 크기를 자세히 설명하지 않았기 때문에 관계형 데이터베이스 외부의 다른 최적화 기술 (캐시, SQL DB 등).

+0

주소는 사용자뿐 아니라 몇 가지 용도로 사용되므로 사용자 테이블로 이동할 수 없습니다. 예 지역은 도시 지역입니다. 그들은 많은 장소 (도시 이상)에서 사용되기 때문에 독립해야합니다. 좋습니다, 구체화 된 뷰 접근법으로 트리거를 사용하고 있습니다. – ZolaKt