2013-01-14 4 views
2

1 데이터베이스 : 사용자 - 사진 - 투표
는 - 사용자가 많은 사진을 가질 수 있습니다.
- 사진에 여러개의 표가있을 수 있습니다.
- 사용자가 여러 사진에 투표 할 수 있습니다.
- 투표 기록 :
. 결과는 int (-1/싫어하는 것, 0/중립적 인 것, 1/좋아하는 것)
입니다. 투표 한 사용자의 ID입니다. 여기MySQL의 3 방향 1..N 테이블 관계


내가 가진 것입니다 (모든 FKS은 삭제 및 업데이트에 대한 캐스케이드입니다) :
http://grab.by/iZYE
(SID = 대리 ID)

내 질문은 :이 바로 것, 내가하지 않습니다 이미 2 일 동안 이것을보고 자신있게 움직일 수는 없습니다. 어떻게 이것을 최적화 할 수 있습니까? 아니면 완전히 잘못 되었습니까?

+0

"sid"는 무엇입니까? 사용자 목록 (user_id *), 사진 테이블 (photo_id *) 및 투표 표 (user_id *, photo_id *, 투표)가 거의 있음을 알 수 있습니다. [* = (구성 요소) PRIMARY KEY. – Strawberry

+0

sid = 대리 ID (자동 증가 인덱스 PK) – jerrytouille

+0

[투표]는 투표 한 사용자에게만 사진의 "소유자"에게 FK가 필요하지 않으므로 photo_user_sid가 중복됩니다. 그게 도움이 되니? – CHill60

답변

1

MySQL/InnoDB 테이블은 항상 클러스터링됩니다 (클러스터링에 대해서는 herehere).

기본 키는 의 역할을하기 때문에 서로 게이트 키를 사용하면 클라이언트 응용 프로그램에 유용한 의미가없고 쿼리에 사용할 수없는 순서로 실제로 테이블을 정렬합니다.

클러스터 된 테이블의 보조 인덱스는 힙 기반 테이블보다 "더 쓸만한"수 있으며 이중 조회가 필요할 수 있습니다. 이러한 이유로

, 당신은 서로 게이트를 방지하고 이와 유사한 더 "자연"키를 사용하고자하는 것 : 테이블에

enter image description here

({USER_ID, PICTURE_NO}VOTE 참조를 PICTURE에서 같은 이름의 필드 가능한 경우 *_ID*_NO 필드의 정수를 사용하십시오. VOTE.VOTER_IDUSER.USER_ID입니다.) 지정된 사용자의

  • 사진 (PICTURE 차/클러스터링 인덱스에 대한 간단한 범위 스캔 :)

    이 물리적 모델은 매우 효율적인 쿼리를 가능하게 할 것이다.

  • 주어진 사진에 투표 (VOTE 기본/클러스터링 색인의 간단한 범위 스캔). 상황에 따라 실제로는 빠르기 때문에 합계를 PICTURE에 캐시 할 필요가 없습니다.

주어진 사용자의 투표가 필요한 경우 VOTE PK를 {VOTER_ID, USER_ID, PICTURE_NO}으로 변경하십시오. 두 가지 (그림 투표와 사용자 투표)가 필요한 경우 기존 PK를 유지하고 {VOTER_ID, USER_ID, PICTURE_NO, VOTE_VALUE}covering 색인을 만드십시오.


이노에서

1

. 클러스터링 키가 기본 데이터베이스와 다를 수있는 DBMS (예 : MS SQL Server)가 있습니다.

+0

"{VOTER_ID, USER_ID, PICTURE_NO, VOTE_VALUE}에 표지 색인 만들기"를 사용하면 자동 증가 색인을 추가하는 것이지만 PK가 아니게 만들겠습니까? – jerrytouille

+0

@jerrytouille이 값은 생성되는 방법과 관련이 없지만 인덱스에 포함되는 필드는 무엇입니까? 일반 인덱스는 WHERE/JOIN에 언급 된 필드를 포함하지만 커버 리지 인덱스는 SELECT 목록에 언급 된 필드도 포함합니다. 이것은 DBMS가 "main"테이블 (InnoDB의 경우 테이블 힙 또는 B- 트리)을 건드리지 않고 인덱스 _alone_에 액세스하여 쿼리를 실행할 수 있도록합니다. 철저한 설명을 위해 제공된 링크를 따라주십시오. 결국, 당신은 PK'{USER_ID, PICTURE_NO, VOTER_ID}'_ 및 _ 인덱스'{VOTER_ID, USER_ID, PICTURE_NO, VOTE_VALUE}'를 갖게 될 것입니다. –

+0

흠. 꽤 멋지다. 내 리그에서 조금 벗어나서 잠깐 들어가야한다. 내가 모든 것을 정확하게 이해한다면 : 모든 대리자 ID (자동 증분 인덱스) PKs를 제거하고 실제 비즈니스 PKs (' user_id ','photo_id '...), 사용되는 유일한 색인은 VOTE 테이블에 대한 {VOTER_ID, USER_ID, PICTURE_NO, VOTE_VALUE}의 표지 색인입니다. 그것에 대한 나의 질문은 : 우리가 그것을 디자인 할 때 테이블에 추가 된 여분의 열로 커버 링 인덱스를 만들거나 쿼리를 실행할 때 우리가하는 일인가? – jerrytouille

1

가장 먼저 보는 것은 테이블에 중복 된 고유 ID가 있다는 것입니다. sid 열은 필요하지 않습니다. user_id, photo_idphoto_user_id을 사용하십시오 (이 이름을 vote_id으로 바꿀 수 있습니다). 해당 ID 열도 INT 유형이어야하며 정확히 VARCHAR이 아닙니다. photo에 투표 총계 열이 필요하지 않을 수도 있습니다. 쿼리를 실행하여 필요시 합계를 얻고 두 테이블을 동기화 상태로 유지하는 것에 대해 걱정할 필요가 없습니다.

사진 당 사용자 당 투표 수를 1 회로 허용한다고 가정하면 그 구조는 수정할 수 있으므로 user_id, photo_idvote_result입니다. 그런 다음 기본 키를 (user_id, photo_id)의 복합 인덱스로 만듭니다. 그러나 외래 키를 사용하기 때문에이 테이블이 좀 더 복잡해집니다.

+0

실제로 모든 'sid'는 대리자 기본 키입니다. 'user_id'는 uniqid()가 생성되고, 'photo_id'는 나중에 사용하기 위해 저장됩니다. 그들은 열쇠가 아닙니다. 'photo_user_id'는 '사진'에서 '투표'까지 1..n 일 때 '투표'테이블의 'sid'인 'vote_id'가 아닌 경우 MySQL Workbench에서 생성됩니다. – jerrytouille

+0

"대리자 기본 키"가 무슨 뜻인지 잘 모르겠지만 필요하지 않아야합니다. 그들이 원래 스키마에서 사용되는 방식은 각 테이블의 고유 한 ID로,'user_id' 컬럼을 쓸모 없게 만듭니다. 테이블의 각 행에 고유 한 ID가 필요한 이유는 무엇입니까? –

+0

stackoverflow (http://stackoverflow.com/questions/63090/surrogate-vs-natural-business-keys)에 내가이 거대한 논쟁을 여기에 도달 할 때까지 대리 키에 관해서 똑같은 생각이 들었다. 왜 내가 가지고 놀고있는 프로젝트의 다른 측면입니다 내 로컬 안드로이드 sqlite DB를 위해 사용하는 여분의 고유 한 ID입니다. – jerrytouille