데이터베이스에서 주석 및 좋아요 구현


146

저는 소프트웨어 개발자입니다. 코딩을 좋아하지만 데이터베이스가 싫습니다 ... 현재 사용자가 엔티티를 좋아 하는 것으로 표시 (FB와 같이)하고 태그를 지정하고 주석을 달 수있는 웹 사이트를 만들고 있습니다 .

이 기능을 처리하기 위해 데이터베이스 테이블 디자인에 갇혀 있습니다. 한 가지 유형의 작업 (예 : 사진)에 대해서만이 작업을 수행 할 수 있으면 해결 방법은 간단합니다. 그러나 나는 이것을 5 가지 다른 것들에 대해 가능하게해야합니다 (현재는 서비스 전체가 커짐에 따라이 숫자가 커질 수 있다고 가정합니다).

비슷한 질문이 있지만 만족스러운 답변이 없으므로이 질문을 다시 묻습니다.

문제는 제대로하는 방법이며, 효율적으로 하고 탄성 이 다른에 대한 의견을 저장할 수 그래서, 데이터베이스를 설계 테이블 , 좋아하는 다른위한 테이블태그 그들을 위해. 대답으로 일부 디자인 패턴이 가장 좋습니다.)

자세한 설명 : 나는이 테이블 User 일부 사용자 데이터, 3 개 테이블 : Photo사진 , Articles기사 , Places장소 . 로깅 된 사용자가 다음을 수행 할 수있게하고 싶습니다.

  • 이 세 가지 표 중 하나에 의견

  • 그들 중 하나를 좋아하는 것으로 표시

  • 태그를 사용하여 태그를 지정하십시오

  • 또한 모든 요소에 대한 좋아요 수와 특정 태그가 사용 된 횟수를 세고 싶습니다.

1 접근법 :

A)를 들어 태그 , 나는 만듭니다 테이블을 Tag [TagId, tagName, tagCounter] , 그때가 만들 대다 관계 테이블을 위해 : Photo_has_tags, Place_has_tag, Article_has_tag.

b) 의견도 마찬가지입니다.

C) 나는 만듭니다 테이블을 LikedPhotos [idUser, idPhoto] , LikedArticles[idUser, idArticle], LikedPlace [idUser, idPlace]. 수 좋아하는가 에 의해 계산됩니다 쿼리 (I 나쁜 가정). 과...

나는 마지막 부분에 대해이 디자인이 마음에 들지 않습니다. 나에게 나쁜 냄새가납니다.)


2 접근법 :

나는 테이블이 만들어집니다 ElementType [idType, TypeName == some table name]의 이름 관리자 (나)에 의해 채워집니다 테이블 수 있습니다 좋아 , 주석 또는 태그를 . 그런 다음 테이블 을 만듭니다 .

a) LikedElement [idLike, idUser, idElementType, idLikedElement]각각에 대해 적절한 열이있는 주석 및 태그에 대해 동일합니다. 이제 사진을 좋아하게 만들려면 다음을 삽입하십시오.

typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo'
INSERT (user id, typeId, photoId)

그리고 장소 :

typeId = SELECT id FROM ElementType WHERE TypeName == 'Place'
INSERT (user id, typeId, placeId)

등등 ... 저는 두 번째 접근 방식이 더 낫다고 생각하지만,이 디자인에서도 뭔가 빠진 것 같은 느낌이 듭니다 ...

마지막으로, 나는 그 요소가 몇 번이나 좋아되었는지 카운터를 저장할 가장 좋은 곳이 무엇인지 궁금합니다. 두 가지 방법 만 생각할 수 있습니다.

  1. 요소 ( Photo/Article/Place) 테이블
  2. count ()를 선택하십시오.

이 문제에 대한 나의 설명이 더 철저 해지기를 바랍니다.


XML을 고려 했습니까?
CodyBugstein

1
나는 내 마음에 100 %와 같은 질문을 거의 찾지 않습니다. 귀하의 질문은 훌륭하게 완료되었습니다! 감사합니다 @Kokos.
aderchox

답변:


195

가장 확장 가능한 솔루션은 하나의 "기본"테이블 ( "좋아요", 태그 및 주석에 연결됨)을 갖고 다른 모든 테이블을 "상속"하는 것입니다. 새로운 종류의 엔터티를 추가하려면 새로운 "상속 된"테이블을 추가하면됩니다. 그러면 자동으로 전체 유사 / 태그 / 코멘트 기계에 연결됩니다.

이에 대한 엔티티 관계 용어는 "카테고리"입니다 ( ERwin 메소드 안내서 , "서브 타입 관계"섹션 참조 ). 카테고리 기호는 다음과 같습니다.

범주

사용자가 여러 엔티티를 좋아할 수 있다고 가정하면 동일한 태그를 둘 이상의 엔티티에 사용할 수 있지만 주석은 엔티티마다 다르므로 모델은 다음과 같습니다.

응급실 다이어그램


BTW에는 "ER 카테고리"를 구현하는 대략 3 가지 방법이 있습니다.

  • 하나의 테이블에있는 모든 유형.
  • 별도의 테이블에있는 모든 콘크리트 유형.
  • 별도의 테이블에있는 모든 콘크리트 및 추상 유형.

매우 엄격한 성능 요구 사항이 없으면 세 번째 방법이 가장 좋습니다 (물리 테이블이 위 다이어그램의 엔터티와 1 : 1 일치 함).


2
좋은 답변, 감사합니다. 나는 그것을 구현할 수 있기를 희망합니다 ... 그리고 장고 ORM이 그것을 매핑하기 위해 어떻게 처리 할 것인지 궁금합니다 (또는 내가 직접 할 것입니다 ... 그러나 다른 문제입니다; 나, 나는 그것을 제대로 이해하지 못한다고 생각하기 때문에-당신이 나에게 그린 것은 (감사합니다!) 당신이 언급 한 세 번째 접근법입니까?
Kokos

2
@Kokos 기본적으로 접근 방식 (3)은 ENTITY가 테이블이고 PHOTO는 테이블, ARTICLE은 테이블, PLACE는 테이블임을 의미합니다. 접근법 (2)는 ENTITY에 대한 테이블 이 없음을 의미 하고 접근법 (1)은 하나의 테이블 만 있음을 의미합니다. 이러한 모든 접근법 (강점과 약점 모두)의 존재는 전형적인 RDBMS가 기본적으로 테이블 상속을 지원하지 않는다는 사실의 불행한 결과입니다.
Branko Dimitrijevic

1
"범주"에 대한 훌륭한 설명과 참고 자료에 대해 +1 감사합니다. 나는 이것에 가까운 질문을 게시하려고했지만 여기에 대답했습니다.
andy holaday

2
@BrankoDimitrijevic 왜 엔티티 테이블 Photo, Article, Place가 PhotoID, ArticleID 등과 같은 PK를 가질 수없고 Entity_ID에 대한 다른 열을 FK로 가질 수 없습니까? 이것이 불필요합니까?
1 권

3
@Orion 최대 값 BIGINT은 9223372036854775807입니다. 초당 1 행씩 삽입한다고 가정하면 ~ 300 억년 안에 사용 가능한 값이 소진됩니다. 그때까지는 128 비트 정수로 포팅 할 수 있습니다!
Branko Dimitrijevic

22

데이터베이스를 "증오"하기 때문에 왜 데이터베이스를 구현하려고합니까? 대신,이 물건을 사랑하고 호흡하는 사람의 도움을 요청하십시오.

그렇지 않으면 데이터베이스를 사랑하는 법을 배우십시오. 잘 설계된 데이터베이스는 프로그래밍을 단순화하고 사이트를 엔지니어링하며 지속적인 운영을 원활하게합니다. 숙련 된 d / b 디자이너조차 완벽하고 완벽한 예측력을 갖지 못할 것입니다. 사용 패턴이 나타나거나 요구 사항이 변경 될 때 일부 스키마 변경이 필요합니다.

이것이 단일 사용자 프로젝트 인 경우 저장 프로 시저 (add_user, update_user, add_comment, add_like, upload_photo, list_comments 등)를 사용하여 데이터베이스 인터페이스를 간단한 조작으로 프로그래밍하십시오. 스키마를 한 줄의 코드로 포함하지 마십시오. 이러한 방식으로 데이터베이스 스키마는 코드에 영향을주지 않고 변경 될 수 있습니다. 스토어드 프로 시저 만 스키마에 대해 알아야합니다.

스키마를 여러 번 리팩토링해야 할 수도 있습니다. 이것은 정상입니다. 처음부터 완벽하게 만드는 것에 대해 걱정하지 마십시오. 초기 디자인의 프로토 타입을 제작할 수있을 정도로 기능적으로 만드십시오. 호화로운 시간이 있다면 일부를 사용한 다음 스키마를 삭제하고 다시 수행하십시오. 그것은이다 항상 더 나은 두 번째 시간입니다.


2
직접 구현해야하기 때문입니다. 적어도 지금은 ... 그리고 아마도 데이터베이스를 조금 좋아하는 것이 좋은 기회라고 생각했습니다.) 저장 프로 시저에 대한 제안에 감사드립니다. Django ORM이 자동으로 매핑하면 누군가 알고 있습니까?
Kokos

6
나는 당신의 마지막 문장을 좋아합니다- 항상 두 번째로 좋습니다.
Lewis

2
항상 두 번째로 좋습니다. Yup
Gammer

20

이것은 일반적인 아이디어입니다. 필드 이름 스타일링에 많은 관심을 기울이지 말고 관계 및 구조에 더 많은주의를 기울이십시오.

여기에 이미지 설명을 입력하십시오

이 의사 코드는 ID 5
SELECT * FROM actions
WHERE actions.id_Stuff = 5
AND actions.typeStuff = "photo" 인 사진의 모든 주석을 가져옵니다.
과 actions.typeAction = "코멘트"

이 의사 코드는 ID 5의 사진을 좋아하는 모든 좋아요 또는 사용자를
얻습니다 (카운트 수를 얻으려면 count ()를 사용할 수 있습니다)

SELECT * FROM actions  
WHERE actions.id_Stuff = 5  
AND actions.typeStuff="photo"  
AND actions.typeAction = "like"  

코멘트에서 "like"링크를 클릭하는 것처럼 코멘트를 좋아할 수도 있습니다. 이 쿼리는 ID가 133 인 주석 (action)을 좋아합니다. SELECT * FROM actions WHERE actions.id=133 AND actions.typeStuff = "comment" AND actions.typeAction = "like"
user964260

1
시스템의 추가 릴리즈를 위해이 솔루션을 확실히 기억할 것입니다 :)
Kokos

stuff1과 stuff2라는 두 가지 테이블이 있습니다 ...이 다이어그램을 따랐지만 이것을 사용하는 동안 SQL 오류가 있습니다 ... stuff1, stuff2는 독립적 인 기본 키가있는 두 개의 독립적 인 테이블이며 작업 테이블에는 참조하는 열 id_stuff가 있습니다. 이 두 테이블은 stuff1, stuff2입니다. 예를 들어 stuff1에는 5 개의 행이 있고 stuff2에는 10 개의 행이 있습니다. id_stuff가있는 작업 테이블에 행을 추가하려고하면 5보다 작은 것은 '3'이라고 말하면 stuff1과 id 모두에 id_stuff '3'이있는 행이 있기 때문에 쿼리를 실행합니다. 나는 5보다 id_stuff 큰 함께 행을 추가하려고하면 stuff2,하지만 ... (다음 주석에 계속)
카스 devde

1
이런 방식으로 좋아요를 구현하는 경우 새로운 좋아요를 사용자에게 알리기가 더 어려워집니다. 다른 테이블이 필요합니다.
Greg L

4
id_stuff열에 세 개의 테이블 각각에 고유 한 값 이 어떻게 포함됩니까?
1 권

0

내가 이해하는 한도에서는. 여러 테이블이 필요합니다. 그들 사이에는 많은 관계가 있습니다.

  • 이름, 성, 생년월일과 같은 사용자 데이터를 ID 필드와 함께 저장하는 테이블입니다.
  • 데이터 유형을 저장하는 테이블입니다. 이러한 유형은 사진, 공유, 링크 일 수 있습니다. 각 유형에는 고유 한 테이블이 있어야합니다. 따라서 개별 테이블과이 테이블 간에는 관계가 있습니다.
  • 각기 다른 데이터 유형에는 테이블이 있습니다. 상태 업데이트, 사진, 링크 등이 있습니다.
  • 마지막 테이블은 ID, 사용자 ID, 데이터 유형 및 데이터 ID를 저장하는 다 대다 관계입니다.

데이터베이스 다이어그램을 게시하면 나는 관계를 그릴 수 있습니다.
erencan

0

필요한 액세스 패턴을보십시오. 그것들 중 어느 것이 나의 하나의 디자인 선택 또는 다른 것을 특히 어렵거나 비효율적으로 만든 것 같습니까?

적은 수의 테이블이 필요한 테이블을 선호하지 않는 경우

이 경우 :

  1. 의견 추가 : 특정 많은 / 많은 테이블을 선택하거나 좋아하는 것으로 알려진 특정 식별자가있는 공통 테이블에 삽입하십시오. 두 번째 경우 클라이언트 코드가 약간 더 간단하다고 생각합니다.
  2. 항목에 대한 의견 찾기 : 여기에서 공통 테이블을 사용하는 것이 약간 더 쉬운 것 같습니다. 엔티티 유형별로 매개 변수가 지정된 단일 쿼리 만 있습니다.
  3. 한 가지 종류의 것에 대한 사람의 의견 찾기 : 두 경우 모두 간단한 쿼리
  4. 모든 것에 대한 사람의 모든 의견을 찾으십시오.

옵션 2 인 "차별 된"접근 방식은 경우에 따라 더 간단한 쿼리를 생성하고 다른 경우에는 훨씬 나쁘지 않은 것으로 생각합니다.


0

하나의 테이블이 있고 각 행의 요소 유형을 저장하는 두 번째 방법을 사용하면 유연성이 훨씬 높아집니다. 기본적으로 더 적은 수의 테이블로 논리적으로 작업을 수행 할 수있는 경우 더 적은 수의 테이블로 작업하는 것이 좋습니다. 특정 사례에 대해 지금 내 마음에 떠오르는 한 가지 장점은 특정 사용자의 좋아하는 요소를 모두 삭제하려는 경우를 고려하십시오. 첫 번째 방법은 각 요소 유형에 대해 하나의 쿼리를 실행해야하지만 두 번째 방법으로는 수행 할 수 있습니다 하나의 쿼리로 또는 새 요소 유형을 추가 할 때 고려해야 할 첫 번째 방법으로 각 새 유형에 대한 새 테이블을 작성하지만 두 번째 방법으로는 아무것도하지 않아야합니다 ...


-1

주석 등을 위해 엔티티 당 테이블 사용을 고려하십시오. 더 많은 테이블-더 나은 샤딩 및 스케일링. 내가 아는 모든 프레임 워크에 대해 많은 유사한 테이블을 제어하는 ​​것은 문제가되지 않습니다.

언젠가 그러한 구조에서 읽기를 최적화해야합니다. 기본 테이블 위에 축약 테이블을 쉽게 작성하고 쓰기 작업에서 약간의 손실을 입을 수 있습니다.

사전이있는 하나의 큰 테이블은 언젠가 제어 할 수 없게 될 수 있습니다.


테이블이 많을수록 유지 관리가 용이하지 않습니다. 개별 테이블은 대부분의 d / bs에 의해 분할 될 수 있습니다.
wallyk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.