[sql] 태그 또는 태그 지정을위한 권장 SQL 데이터베이스 디자인 [닫기]

태그를 구현하는 몇 가지 방법에 대해 들었습니다. TagID와 ItemID 사이의 매핑 테이블을 사용하면 (나에게 이해가되지만 확장 가능합니까?) 고정 가능한 수의 TagID 열을 ItemID에 추가 (나쁜 생각처럼 보임), 쉼표로 구분 된 텍스트 열에 태그 유지 (소리) 미친하지만 작동 할 수 있습니다). 누군가 희소 행렬을 추천한다고 들었지만 태그 이름이 어떻게 우아하게 커 집니까?

태그에 대한 모범 사례가 누락 되었습니까?



답변

적절한 데이터베이스에서 실행되는 외래 키를 사용하여 올바르게 인덱스 된 세 개의 테이블 (하나는 모든 항목을 저장하기위한 것, 하나는 모든 태그 및 하나의 관계를위한 것임)이며 제대로 작동하고 적절하게 확장되어야합니다.

Table: Item
Columns: ItemID, Title, Content

Table: Tag
Columns: TagID, Title

Table: ItemTag
Columns: ItemID, TagID


답변

일반적으로 Yaakov Ellis에 동의하지만이 특별한 경우에는 다른 가능한 해결책이 있습니다.

두 개의 테이블을 사용하십시오.

Table: Item
Columns: ItemID, Title, Content
Indexes: ItemID

Table: Tag
Columns: ItemID, Title
Indexes: ItemId, Title

여기에는 몇 가지 주요 장점이 있습니다.

먼저 삽입과 업데이트를위한 3 테이블 솔루션에서 이미 항목이 있는지 확인하기 item위해 Tag테이블을 조회해야 합니다. 그런 다음 새로운 것들과 함께해야합니다. 이것은 사소한 일이 아닙니다.

그런 다음 쿼리가 더 간단하고 빠릅니다. 세 가지 주요 데이터베이스 쿼리가 있습니다. Tags하나를 모두 출력 Item하고 Tag-Cloud를 그리고 하나의 태그 제목에 대한 모든 항목을 선택하십시오.

하나의 항목에 대한 모든 태그 :

3- 테이블 :

SELECT Tag.Title
  FROM Tag
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 WHERE ItemTag.ItemID = :id

2 테이블 :

SELECT Tag.Title
FROM Tag
WHERE Tag.ItemID = :id

태그 클라우드 :

3- 테이블 :

SELECT Tag.Title, count(*)
  FROM Tag
  JOIN ItemTag ON Tag.TagID = ItemTag.TagID
 GROUP BY Tag.Title

2 테이블 :

SELECT Tag.Title, count(*)
  FROM Tag
 GROUP BY Tag.Title

하나의 태그에 대한 항목 :

3- 테이블 :

SELECT Item.*
  FROM Item
  JOIN ItemTag ON Item.ItemID = ItemTag.ItemID
  JOIN Tag ON ItemTag.TagID = Tag.TagID
 WHERE Tag.Title = :title

2 테이블 :

SELECT Item.*
  FROM Item
  JOIN Tag ON Item.ItemID = Tag.ItemID
 WHERE Tag.Title = :title

그러나 몇 가지 단점도 있습니다. 데이터베이스에서 더 많은 공간을 차지할 수 있고 (더 많은 디스크 작업으로 인해 속도가 느려질 수 있음) 정규화되지 않아 불일치가 발생할 수 있습니다.

태그의 특성은 일반적으로 매우 작기 때문에 크기 증가가 크지 않기 때문에 크기 인수는 그렇게 강력하지 않습니다. 태그 제목에 대한 쿼리는 각 태그를 한 번만 포함하는 작은 테이블에서 훨씬 빠르며 확실히 사실입니다. 그러나 가입 할 필요가없는 절약 효과와 좋은 인덱스를 만들 수 있다는 사실을 고려하면이를 쉽게 보상 할 수 있습니다. 물론 이것은 사용중인 데이터베이스의 크기에 따라 크게 다릅니다.

불일치 주장도 약간의 문제입니다. 태그는 자유 텍스트 필드이며 ‘모든 태그 이름을’foo ‘에서’bar ‘로 바꾼’과 같은 예상 작업이 없습니다.

그래서 tldr : 나는 두 테이블 솔루션을 갈 것입니다. (사실 것입니다.이 기사에서 이에 대한 유효한 논증이 있는지 확인했습니다.)


답변

couchdb와 같이 map-reduce를 지원하는 데이터베이스를 사용하는 경우 일반 텍스트 필드 또는 목록 필드에 태그를 저장하는 것이 가장 좋습니다. 예:

tagcloud: {
  map: function(doc){
    for(tag in doc.tags){
      emit(doc.tags[tag],1)
    }
  }
  reduce: function(keys,values){
    return values.length
  }
}

group = true로 이것을 실행하면 태그 이름별로 결과를 그룹화하고 태그가 발생한 횟수를 반환합니다. text에서 단어의 발생 횟수계산하는 것과 매우 유사 합니다 .


답변

태그를 저장하는 데 단일 형식의 텍스트 열 [1]을 사용하고이를 가능하게하는 전체 텍스트 검색 엔진을 사용하십시오. 그렇지 않으면 부울 쿼리를 구현하려고 할 때 스케일링 문제가 발생합니다.

보유한 태그에 대한 세부 사항이 필요한 경우 점진적으로 유지 보수 된 테이블에서 태그를 추적하거나 배치 작업을 실행하여 정보를 추출 할 수 있습니다.

[1] 일부 RDBMS는 구문 분석 단계를 필요로하지 않아도 저장에 더 적합한 기본 배열 유형을 제공하지만 전체 텍스트 검색에 문제를 일으킬 수 있습니다.


답변

나는 항상 태그를 별도의 테이블에 보관 한 다음 매핑 테이블을 가졌습니다. 물론 나는 정말 큰 규모로 아무것도 한 적이 없습니다.

“태그”테이블과 맵 테이블을 사용하면 태그 클라우드를 생성하기가 쉽지 않습니다. SQL을 쉽게 결합하여 각 태그가 얼마나 자주 사용되는지에 대한 수를 가진 태그 목록을 얻을 수 있기 때문입니다.


답변

다음 디자인을 제안합니다. Item Table : Itemid, taglist1, taglist2
빠르고 빠르며 항목 수준에서 데이터를 쉽게 저장하고 검색 할 수 있습니다.

병렬로 다른 테이블 만들기 : 태그 태그는 태그를 고유 식별자로 만들지 않으며 두 번째 열의 공간이 부족하면 100 개의 항목이 다른 행을 만들 수 있습니다.

이제 태그 항목을 검색하는 동안 매우 빠릅니다.


답변