2009-03-19 4 views
6

EDIT : 건물 태그 시스템에 사람들에게. 이것을 읽지 마십시오. 그것은 당신이 찾고있는 것이 아닙니다. 나는 RDBMS가 모두 자신의 최적화 방법을 가지고 있다는 것을 알지 못했을 때이 질문을 던졌다. 단순한 many to many scheme을 사용했다.확장 가능한 데이터베이스 태깅 스키마

나는 수백만 개의 게시물이있는 게시 시스템을 가지고 있습니다. 각 게시물은 무한 수의 태그를 가질 수 있습니다.

사용자는 메모, 만든 날짜, 소유자 등이있는 태그를 만들 수 있습니다. 태그는 게시물 자체와 비슷합니다. 사람들이 태그에 대한 메모를 게시 할 수 있기 때문입니다.

각 태그 연관에는 소유자와 날짜가 있으므로 누가 태그를 추가했는지 확인할 수 있습니다.

내 질문은 어떻게 구현할 수 있습니까? 태그로 게시물을 빠르게 검색하거나 게시물별로 태그를 검색해야합니다. 또한 사용자는 Google 검색 창과 같이 필드에 이름을 입력하여 게시물에 태그를 추가 할 수 있으며 태그 이름의 나머지 부분을 채워야합니다.

현재로서는 3 가지 해결책이 있지만 어느 것이 가장 좋을지 또는 더 좋은 방법이 있는지 확실하지 않습니다.

태그에 대한 적절한 해결책을 얻은 후에는 평소와 다르기 때문에 메모 레이아웃을 표시하지 않습니다.

방법 1. 링크 된 목록 tag_assoc에서 연결된 목록에 포스트 포인트

tagId는 응용 프로그램이 FLINK = 0

post:   id, content, ownerId, date, tagId, notesId 
tag_assoc:  id, tagId, ownerId, flink 
tag:   id, name, notesId 

방법 2 비정규

태그까지 목록을 통과해야한다 tagId : ownerId의 탭으로 구분 된 배열을 포함하는 VARCHAR 또는 TEXT 필드입니다. 고정 크기 일 수는 없습니다.

post:   id, content, ownerId, date, tags, notesId 
tag:   id, name, notesId 

방법 3. Toxi

(에서 : http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html, 도 같은 일을 여기 : Recommended SQL database design for tags or tagging)

방법 3이 문제를 제기

post:   id, content, ownerId, date, notesId 
tag_assoc:  ownerId, tagId, postId 
tag:   id, name, notesId 

, 어떻게 빨리 모든 반복하는 것 tag_assoc의 단일 행?

방법 1과 2는 태그로 게시물을 반환하는 데 빠르지 만 태그로 게시물을 작성하려면 다른 조회 테이블을 만들어야합니다.

내가 걱정해야 할 마지막 사항은 태그를 검색하여 이름을 최적화하는 것입니다. 아직 해결하지 못했습니다.

나는 여기에 ASCII도했다 ". 사람들이 태그에 대한 메모를 게시 할 수 있기 때문에 태그는 거의 게시물 자체 같다" http://pastebin.com/f1c4e0e53

답변

0

Bill 나는 당신을 버렸다고 생각합니다. 노트는 다른 테이블에 있으며 다른 사람들이 게시 한 노트가있는 별도의 테이블이 있습니다. 게시물에는 메모와 태그가 있지만 태그에도 메모가 있으므로 태그가 고유합니다.

조나단은 링크 된 목록에 대한 권리가 있습니다. 나는 전혀 사용하지 않을 것입니다. 나는 내 요구 고기 간단한 표준화 된 방법으로 태그를 구현하기로 결정 :

DROP TABLE IF EXISTS `tags`; 
CREATE TABLE IF NOT EXISTS `tags` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `owner` int(10) unsigned NOT NULL, 
    `date` int(10) unsigned NOT NULL, 
    `name` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `name` (`name`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

DROP TABLE IF EXISTS `posts`; 
CREATE TABLE IF NOT EXISTS `posts` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `owner` int(10) unsigned NOT NULL, 
    `date` int(10) unsigned NOT NULL, 
    `name` varchar(255) NOT NULL, 
    `content` TEXT NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

DROP TABLE IF EXISTS `posts_notes`; 
CREATE TABLE IF NOT EXISTS `posts_notes` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `owner` int(10) unsigned NOT NULL, 
    `date` int(10) unsigned NOT NULL, 
    `postId` int(10) unsigned NOT NULL, 
    `note` TEXT NOT NULL, 
    PRIMARY KEY (`id`), 
    FOREIGN KEY (`postId`) REFERENCES posts(`id`) ON DELETE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

DROP TABLE IF EXISTS `posts_tags`; 
CREATE TABLE IF NOT EXISTS `posts_tags` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `owner` int(10) unsigned NOT NULL, 
    `tagId` int(10) unsigned NOT NULL, 
    `postId` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`id`), 
    FOREIGN KEY (`postId`) REFERENCES posts(`id`) ON DELETE CASCADE, 
    FOREIGN KEY (`tagId`) REFERENCES tags(`id`) ON DELETE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

나는이 미래에 얼마나 빨리 확실하지 않다, 그러나 그것은 잠시 동안 괜찮을 것 같으며 단지 몇 사람들 데이터베이스를 사용하십시오.

0

을 -이 문구는 POST를 참조하는 기본 키와 외래 키와 함께 POST에 대해 하나의 테이블 만 필요하다고 생각하게 만듭니다. 이제 디스크 공간이 허용하는만큼 각 게시물에 대해 많은 태그를 가질 수 있습니다.태그가 게시물에서 공유되지 않기 때문에

나는이에 따라, POST와 태그 사이에 많은에 많은 필요가 없습니다 있으리라 믿고있어 :

"사용자 메모, 날짜가 만든 태그를 만들 수 있습니다, 소유자 등 "

작성 날짜와 소유자를 공유하는 경우 두 개의 추가 외래 키 관계 인 IMO가됩니다. 여기

+0

태그는 게시물간에 공유됩니다. 나는 방법 3을 꽤 많이 결정했다. 태그를 가질 수있는 모든 테이블에는 _tags라는 다른 테이블이 있습니다. 예 : news_tags. 저는이 방법에 대해 여전히 일종의 스케치이지만, 모든 사람들이 그것을 추천하는 것처럼 보이므로 MySQL이이를 최적화한다고 가정하고 있습니다. –

+0

"가정"- 나쁜 생각입니다. 알면 더 좋습니다. – duffymo

2

내가 그것을 할 거라고 방법은 다음과 같습니다 대괄호

posts:   [postId], content, ownerId, date, noteId, noteType='post' 
tag_assoc:  [postId, tagName], ownerId, date, noteId, noteType='tagAssoc' 
tags:   [tagName], ownerId, date, noteId, noteType='tag' 
notes:   [noteId, noteType], ownerId, date, content 

필드는 각 테이블의 기본 키입니다.

posts, tag_assoctags의 각 테이블에서 noteType에 대한 제약 조건을 정의하십시오. 이렇게하면 특정 노트가 posttag에 모두 적용되는 것을 방지 할 수 있습니다.

태그 이름을 짧은 문자열로 저장하고 정수가 아닌 id으로 저장하십시오. 그렇게하면 tag_assoc 테이블에 덮고 색인 [postId, tagName]을 사용할 수 있습니다.

태그 지정 완료는 AJAX 호출로 완료됩니다. 사용자가 태그에 대해 "datab"을 입력하면 웹 페이지가 AJAX 호출을하고 서버 측에서 앱은 SELECT tagName FROM tags WHERE tagName LIKE ?||'%'을 쿼리합니다.

0

연결 목록은 거의 틀린 방식입니다. 즉, 연결된 목록을 사용하는 가장 큰 이유는 데이터를 올바른 정렬 된 순서로 유지하는 것이기 때문에 쿼리가 복잡하거나 차선책 인 것입니다. 그러나 반복적으로 행을 가져 오는 것을 피하고 다음 행의 선택 작업을 조건 지정하기 위해 검색된 flink 값을 사용하는 쉬운 방법은 없습니다.

따라서 기본 키 참조에 대한 일반 외래 키가있는 테이블 기반 접근 방식을 사용하십시오. 빌 Karwin에 의해 개설 된 것은 내가 개략적으로 설명하는 것과 유사합니다.

관련 문제