복붙노트

[SQL] 태그에 대한 데이터베이스 설계

SQL

태그에 대한 데이터베이스 설계

다음 태그 기능을 지원하는 데이터베이스를 설계 할 방법 :

이상적으로, (적어도)와 n은 주어진 태그 집합 태그 된 모든 항목의 검색은 단일 SQL 문을 사용하여 수행해야합니다. 태그의 수를 알 수뿐만 아니라 모든 항목에 태그 번호를 검색하고 높은 수 있기 때문에, 사용하는 것은 비현실적이다 결합합니다.

어떤 아이디어?

지금까지 모든 해답을 주셔서 감사합니다.

제가 잘못 본게 아니라면, 그러나 주어진 응답 태그에 대해 OR 검색을 수행하는 방법을 보여줍니다. (N 태그 중 하나 이상있는 모든 항목을 선택합니다). 나는 효율적인 AND 검색을 찾고 있어요. (ALL n 개의 태그가 모든 항목 선택 -. 그리고 아마도 이상)

해결법

  1. ==============================

    1.AND 연산에 관하여 : 그것은 당신이 "관계 부서"작업을 찾고있다처럼 들린다. 이 글은 간결에서 관계 부문 아직 comprehendible 방법을 설명합니다.

    AND 연산에 관하여 : 그것은 당신이 "관계 부서"작업을 찾고있다처럼 들린다. 이 글은 간결에서 관계 부문 아직 comprehendible 방법을 설명합니다.

    성능 정보, • 비트 맵 기반의 접근 방식은 직관적으로이 상황을 잘 맞는 것 같군요. (?) 새로운 태그가 추가 그러나 제공 비트 맵 인덱스 (오라클 포함) 일부의 DBMS하는 어떻게 든 할 수있다 때마다 그것은 복잡한 상황처럼 들린다 : 그러나, 나는 digiguru이 시사하는 것처럼, "수동"비트 맵 색인을 구현하는 좋은 아이디어입니다 확신 아니에요 사용 될 때문에 내장 된 인덱싱 시스템 인덱스 유지 보수의 잠재적 인 복잡성을 멀리하지; 또한, 비트 맵 인덱스를 제공하는 DBMS 쿼리 계획을 수행 할 때 때 적절한 그들을 고려할 수 있어야한다.

  2. ==============================

    2.다음은 데이터베이스 스키마를 태그에 대한 좋은 기사입니다 :

    다음은 데이터베이스 스키마를 태그에 대한 좋은 기사입니다 :

    http://howto.philippkeller.com/2005/04/24/Tags-Database-schemas/

    성능 테스트와 함께 :

    http://howto.philippkeller.com/2005/06/19/Tagsystems-performance-tests/

    결론은 (작성 당시 2005 년에 적어도) 매우 가난 전체 텍스트 인덱싱 특성을 가지고 MySQL은, 매우 구체적인 있다는 것을 참고.

  3. ==============================

    3."태그"에 대한 crosstable 항목, 태그 테이블, 표 : 나는 간단한 솔루션으로 문제를 볼 수 없습니다

    "태그"에 대한 crosstable 항목, 태그 테이블, 표 : 나는 간단한 솔루션으로 문제를 볼 수 없습니다

    크로스 테이블에 인덱스 충분히 최적화해야합니다. 적절한 항목을 선택하면 될 것이다

    SELECT * FROM items WHERE id IN  
        (SELECT DISTINCT item_id FROM item_tag WHERE  
        tag_id = tag1 OR tag_id = tag2 OR ...)  
    

    와 태그는 것

    SELECT * FROM items WHERE  
        EXISTS (SELECT 1 FROM item_tag WHERE id = item_id AND tag_id = tag1)  
        AND EXISTS (SELECT 1 FROM item_tag WHERE id = item_id AND tag_id = tag2)  
        AND ...
    

    이는 비교 태그 많은 수의 그렇게 효율적이지, 틀림없이입니다. 당신이 메모리에 태그 카운트를 유지하는 경우, 당신은 너무과 순서 빨리 평가 될 것입니다, 종종 있습니다 태그로 시작하는 쿼리를 만들 수 있습니다. 태그의 예상 수에 따라가에 일치하고 당신이 20 태그와 일치하고,이 여전히 무거운 것이 어떤 임의의 항목 중 15 일치 것으로 기대하는 경우 그 중 하나와 일치의 예상이 확인 해결책이 될 수있다 데이터베이스에.

  4. ==============================

    4.난 그냥 @Jeff 앳 우드로 연결하는 문서 (http://howto.philippkeller.com/2005/04/24/Tags-Database-schemas/) 매우 철저 것을 강조 싶었 (그것은 3 개의 다른 스키마의 장점에 대해 설명 접근)와 대한 좋은 솔루션을 가지고있는 보통 (즉, 그것은 각 용어에 대한 상관 하위 쿼리를 사용하지 않는) 지금까지 여기에 언급 된 것보다 더 나은 수행합니다 쿼리. 코멘트에 좋은 물건도 많이.

    난 그냥 @Jeff 앳 우드로 연결하는 문서 (http://howto.philippkeller.com/2005/04/24/Tags-Database-schemas/) 매우 철저 것을 강조 싶었 (그것은 3 개의 다른 스키마의 장점에 대해 설명 접근)와 대한 좋은 솔루션을 가지고있는 보통 (즉, 그것은 각 용어에 대한 상관 하위 쿼리를 사용하지 않는) 지금까지 여기에 언급 된 것보다 더 나은 수행합니다 쿼리. 코멘트에 좋은 물건도 많이.

    PS - 모두가 여기에 대해 이야기하고 기사에서 "독성"솔루션으로 언급되는 접근.

  5. ==============================

    5.당신은 아파치 루씬 같은 그 위에 구축 된 검색 엔진을 자바 컨텐츠 저장소 구현 (예를 들어, 아파치 잭 래빗) 같은하지-엄격 데이터베이스 솔루션을 실험하고 사용 할 수 있습니다.

    당신은 아파치 루씬 같은 그 위에 구축 된 검색 엔진을 자바 컨텐츠 저장소 구현 (예를 들어, 아파치 잭 래빗) 같은하지-엄격 데이터베이스 솔루션을 실험하고 사용 할 수 있습니다.

    적절한 캐싱 메커니즘이 솔루션은 아마도 자체 개발 솔루션보다 더 나은 성능을 얻을 것이다.

    그러나, 나는 정말 당신이 이전 글에서 언급 한 표준화 된 데이터베이스보다 더 복잡한 구현을 필요로 중소 규모의 응용 프로그램에서 그렇게 생각하지 않습니다.

    편집 : 귀하의 설명과 함께 사용하는 것이 더 매력적인 것 같다 JCR과 같은 검색 엔진 솔루션입니다. 즉 크게 장기적으로 프로그램을 단순화하는 것이다.

  6. ==============================

    6.가장 쉬운 방법은 태그 테이블을 만드는 것입니다. 하며 target_type는 - 경우에 당신이 여러 테이블에 태그를 지정하는 대상 - 레코드의 핵심은 태그되고 태그 - 태그의 텍스트

    가장 쉬운 방법은 태그 테이블을 만드는 것입니다. 하며 target_type는 - 경우에 당신이 여러 테이블에 태그를 지정하는 대상 - 레코드의 핵심은 태그되고 태그 - 태그의 텍스트

    데이터를 쿼리하는 것은 뭔가를 같이 할 것입니다 :

    Select distinct target from tags   
    where tag in ([your list of tags to search for here])  
    and target_type = [the table you're searching]
    

    최신 정보 당신에 대한 요구 사항과 조건을 바탕으로, 위의 쿼리는 다음과 같이 변신 것

    select target
    from (
      select target, count(*) cnt 
      from tags   
      where tag in ([your list of tags to search for here])
        and target_type = [the table you're searching]
    )
    where cnt = [number of tags being searched]
    
  7. ==============================

    7.나는 당신이 (R) DB 중심이 완전히없는 무언가를 할 수 있다는 초 @Zizzencs 제안을 거라고

    나는 당신이 (R) DB 중심이 완전히없는 무언가를 할 수 있다는 초 @Zizzencs 제안을 거라고

    어떻게 든, 나는 일반 NVARCHAR 필드를 사용하여 빠른 결과를 얻을 수있는 몇 가지 적절한 캐싱 / 인덱싱이 태그를 저장할 수 있다고 생각합니다. 하지만 그 날입니다.

    나는 (항목 태그 ItemTags) 전에 다 대다 관계를 표현하기 위해 3 개 테이블을 사용하여 태그 시스템을 구현했습니다,하지만 난 3 표가 갖는 말할 수 있습니다, 당신은 많은 장소에 태그 처리됩니다 가정 조작 / 동시에 모든 시간은 확실히 당신의 코드가 더 복잡 할 것입니다 쿼리.

    추가 된 복잡성이 가치가 있는지 당신은 고려할 필요가 있습니다.

  8. ==============================

    8.당신은 조인 피하기 위해 여전히 다소 정상화 할 수 없습니다.

    당신은 조인 피하기 위해 여전히 다소 정상화 할 수 없습니다.

    내 방법은 태그 표를하는 것입니다.

     TagId (PK)| TagName (Indexed)
    

    그런 다음 항목 테이블의 TagXREFID 열 수 있습니다.

    이 TagXREFID 열이 3 테이블에 FK를, 나는 그것이 TagXREF 전화 할게 :

     TagXrefID | ItemID | TagId
    

    그래서, 같은 될 것이라고 항목에 대한 모든 태그를 얻을 수 있습니다 :

    SELECT Tags.TagId,Tags.TagName 
         FROM Tags,TagXref 
         WHERE TagXref.TagId = Tags.TagId 
             AND TagXref.ItemID = @ItemID
    

    그리고 태그에 대한 모든 항목을 얻기 위해, 나는 이런 식으로 뭔가를 사용하십시오 :

    SELECT * FROM Items, TagXref
         WHERE TagXref.TagId IN 
              ( SELECT Tags.TagId FROM Tags
                    WHERE Tags.TagName = @TagName; )
         AND Items.ItemId = TagXref.ItemId;
    

    함께 태그와 무리에, 당신은 약간 AND Tags.TagName = @ TagName1 및 Tags.TagName = @ TagName2 등을 추가 할 수 ... 동적으로 쿼리를 작성 위의 문을 수정하는 것입니다.

  9. ==============================

    9.IS 그래서이 경우 당신이 가진 것, 원시 데이터를 나타내는 테이블의 번호를 가지고 수행 할 작업 내가 좋아하는

    IS 그래서이 경우 당신이 가진 것, 원시 데이터를 나타내는 테이블의 번호를 가지고 수행 할 작업 내가 좋아하는

    Items (ID pk, Name, <properties>)
    Tags (ID pk, Name)
    TagItems (TagID fk, ItemID fk)
    

    이것은 쓰기 번 빠르게 작동하고, 정상화 모든 것을 유지하지만 천천히 읽기를 가지고, 그래서 당신은 또한 참고 각 태그에, 당신은 당신이 원하는 모든 추가 태그를 두 번 테이블에 가입해야 및합니다 수 있음.

    판독을 향상시키는 해결책은 본질적으로 편평한 형태의 데이터를 나타내는 새로운 테이블을 생성하는 프로 시저를 설정하여 명령에 캐싱 테이블을 작성 ...

    CachedTagItems(ID, Name, <properties>, tag1, tag2, ... tagN)
    

    그런 다음 태그가 지정된 항목 테이블이 모든 삽입에 있다면, 최신 상태로 유지해야하는 빈도를 고려할 수 있습니다 다음, 이벤트 삽입 커서에 저장 프로 시저를 호출합니다. 이 시간당 작업의 경우, 다음을 실행할 수있는 시간마다 작업을 설정합니다.

    이제 데이터 검색에 정말 영리한 얻을, 당신은 태그에서 데이터를 얻을 수있는 저장 프로 시저를 만들 수 있습니다. 오히려 대규모 case 문에 중첩 된 쿼리를 사용하는 것보다, 당신은 당신이 데이터베이스에서 선택하려는 태그의 목록을 포함하는 단일 매개 변수를 전달하고, 항목의 레코드 집합을 반환합니다. 이 비트 연산자를 사용하여, 바이너리 형식으로 가장 좋은 것입니다.

    바이너리 형식에서는 설명하기 쉽습니다. 의 바이너리에 우리가 있음을 나타낼 수, 항목에 할당 할 네 개의 태그가 있다고 가정 해 봅시다

    0000
    

    네 개의 태그가 객체에 할당 된 경우, 객체는 다음과 같이 보일 것 ...

    1111
    

    만약 단지 처음 두 ...

    1100
    

    그런 다음 원하는 열에서 1과 0으로 이진 값을 찾는 단지 사건. SQL 서버의 비트 연산자를 사용하면 매우 간단한 쿼리를 사용하여 컬럼의 첫 번째의 1이 있음을 확인할 수 있습니다.

    자세한 내용을 보려면이 링크를 확인하십시오.

  10. ==============================

    10.말한 다른 사람 의역 : 트릭 스키마에없는, 그것은 쿼리입니다.

    말한 다른 사람 의역 : 트릭 스키마에없는, 그것은 쿼리입니다.

    엔티티 / 레이블의 순진 스키마 / 태그 갈 수있는 올바른 방법이다. 당신이 보았 듯이, 바로 태그를 많이 가진 AND 쿼리를 수행하는 방법을 분명하지 않다.

    나는 당신의 RDBS로 질문을 다시 태그와 "하는 태그 데이터베이스에 최적의 수행 방법 및 쿼리"와 같은 뭔가 제목을 변경하는 것이 좋습니다 그래서 쿼리, 플랫폼에 의존 될 것 최적화 할 수있는 가장 좋은 방법.

    나는 MS SQL에 대한 몇 가지 제안을 가지고 있지만 사용중인 플랫폼이 아니다 경우에 삼가합니다.

  11. ==============================

    11.위의 대답에 대한 변화는 일종의 그들을하는 ^ 구분 된 문자열과 해시 그들로 결합, 태그 ID를 가지고 있습니다. 그리고 단순히 항목에 해시를 연결합니다. 태그의 각 조합은 새 키를 생성합니다. 을하고, 지정된 태그 ID와 해시를 다시 만들 및 검색 간단하게 검색 할 수 있습니다. 항목에 태그를 변경하면 해시가 다시 생성하게됩니다. 태그의 동일한 세트 아이템은 동일한 해시 키를 공유 할 수 있습니다.

    위의 대답에 대한 변화는 일종의 그들을하는 ^ 구분 된 문자열과 해시 그들로 결합, 태그 ID를 가지고 있습니다. 그리고 단순히 항목에 해시를 연결합니다. 태그의 각 조합은 새 키를 생성합니다. 을하고, 지정된 태그 ID와 해시를 다시 만들 및 검색 간단하게 검색 할 수 있습니다. 항목에 태그를 변경하면 해시가 다시 생성하게됩니다. 태그의 동일한 세트 아이템은 동일한 해시 키를 공유 할 수 있습니다.

  12. ==============================

    12.당신이 배열 유형을 한 경우, 당신은-사전 집계 필요한 데이터를 할 수 있습니다. 별도의 스레드에서이 답변을 참조하십시오 :

    당신이 배열 유형을 한 경우, 당신은-사전 집계 필요한 데이터를 할 수 있습니다. 별도의 스레드에서이 답변을 참조하십시오 :

    배열 유형의 유틸리티는 무엇인가?

  13. from https://stackoverflow.com/questions/48475/database-design-for-tagging by cc-by-sa and MIT license