빠른 태그 검색을위한 알고리즘


16

문제는 다음과 같습니다.

  • 간단한 엔터티 E 세트가 있으며 각 태그 세트 T가 부착되어 있습니다. 각 엔티티에는 임의의 수의 태그가있을 수 있습니다. 총 엔터티 수는 거의 1 억 개이며 총 태그 수는 약 5000입니다.

따라서 초기 데이터는 다음과 같습니다.

E1 - T1, T2, T3, ... Tn
E2 - T1, T5, T100, ... Tk
..
Ez - T10, T12, ... Tl

이 초기 데이터는 거의 업데이트되지 않습니다.

  • 어떻게 든 내 응용 프로그램은 다음과 같은 태그에 논리 식을 생성합니다.

    T1 & T2 & T3 | (T5 &! T6)

  • 내가 필요한 것은 주어진 표현과 일치하는 많은 엔티티를 계산하는 것입니다 (주-엔티티가 아니라 숫자). 물론 이것은 완전히 정확하지 않을 수 있습니다.

내가 지금 가지고있는 것은 간단한 메모리 내 테이블 조회로 단일 스레드에서 5-10 초의 실행 시간을 제공합니다.

궁금합니다.이 물건을 처리하는 효율적인 방법이 있습니까? 어떤 접근법을 추천 하시겠습니까? 이것에 대한 일반적인 알고리즘이나 데이터 구조가 있습니까?

최신 정보

요청에 따라 약간의 설명이 필요합니다.

  1. T객체는 실제로 비교적 짧은 상수 문자열입니다. 그러나 실제로는 중요하지 않습니다. 항상 일부 ID를 할당하고 정수로 작동 할 수 있습니다.
  2. 우리는 그것들을 확실히 분류 할 수 있습니다.

1
T1에 대해 동일한 오브젝트 참조 E1, E2등?
Reactgular

태그는 어떻게 비교됩니까? T2 < T3항상 진실 되도록 태그를 정렬 할 수 있습니까?
Reactgular

태그는 바이너리입니까? 즉 입력에 따라 변수가 아닌 주어진 또는 T1하나 입니까? ( ? ) 또는 ? 와 같은 변수 표현식 입니까? truefalseEModel = "V5"T1Model = <input>
Bobson

답변:


4

SQL에서 자체 조인을 사용하여 참조 엔터티와 참조 범주 EntityCategory사이에 링크 테이블이있는 경우이 작업을 수행 합니다.eidcid

    select count(ec1.eid)
    from EntityCategory ec1 
    left join EntityCategory ec2 on ec1.eid=ec2.eid 
    left join EntityCategory ec3 on ec1.eid=ec3.eid 
    ...
    where 
      ec1.cid={categoryId1} and 
      ec2.cid={categoryId2} and
      ec3.cid={categoryId3} ...

1
+1, 이것은 고전적인 DB 영토입니다. 다른 대답은 수동으로 코드를 작성하는 방법에 대한 합리적인 아이디어를 가지고 있지만 마지막 수단이어야합니다.
MSalters

또한 이것을 해결하는 기술로 sql을 선택합니다. 대부분의 데이터베이스는 이러한 알고리즘에 최적화되어 있습니다. :)
winkbrace

3

이 답변을 작성한 후에는이 질문을 "너무 광범위"로 표시해야합니다. 다양한 전략에 대해 오랜 세월 동안 이야기 할 수 있습니다. 결국 벤치 마크를 데이터와 함께 실행해야합니다.

각 태그는 정수로 효율적으로 표현 될 수 있습니다. 각 엔티티에는 태그 세트가 있습니다. 올바른 세트 구현을 선택하는 것이 중요합니다. B- 트리와 정렬 된 배열이 모두 가능합니다. 이 세트를 사용하면 멤버십 테스트 만 수행합니다. 두 구조 모두 O (log t)에서 ( 엔터티 당 t 태그 사용)이 작업을 수행하므로 밀도가 높기 때문에 배열을 선호합니다.

이제 O (n · log t · p) 연산 에서 모든 엔티티를 필터링 할 수 있습니다 . 여기서 p 는 술어 결정 트리의 평균 경로 길이입니다. 이 의사 결정 트리는 의사 결정에 빠르게 도달 할 수 있도록 주문할 수 있습니다. 통계 데이터가 없으면 일반적인 부분 식 만 제외 할 수 있습니다.

엔티티가 검색되는 순서는 실제로 중요하지 않습니다. 다른 한편으로 같은 인덱스의 실체 그런 종류의 것이 유리할 수 있습니다 0i나머지는하지 않지만, 모두가 특정 태그가 있습니다. 이렇게하면 이 특정 태그를 검색 할 때 n 이 줄어 듭니다 (결정 트리에서 첫 번째 테스트 여야 함). 이것은 여러 수준으로 확대하지만,이 복잡 것들과 소요 수 O (2 K ) 와 메모리 K레벨. 여러 수준을 사용하는 경우 게인이 가장 높은 태그를 먼저 결정해야합니다. 여기서 게인은 조회 할 필요가없는 엔터티 수에 버릴 확률을 곱한 것입니다. 50:50 확률 또는 50 %의 엔터티에이 특정 태그가있는 경우 이득이 최대가됩니다. 이를 통해 액세스 패턴을 모르더라도 최적화 할 수 있습니다.

사용 된 각 태그별로 엔터티를 인덱스하는 세트를 만들 수도 있습니다. 하나는에 대한 모든 엔터티가있는 세트 T1입니다 T2. 분명한 (공간 및 시간) 최적화는 세트에 모든 요소의 절반 이상이 포함 된 경우 중지 하고이 태그 가없는 요소를 저장하는 것입니다. 이러한 방식으로 모든 태그에 대한 색인을 작성하면 ½ · n · t공간 보다 적게 걸립니다 ( 총 t 태그). 보완 세트를 저장하면 다른 최적화가 더 어려워 질 수 있습니다. 다시, 나는 세트에 대한 배열을 정렬했습니다.

정수 범위를 통해 엔터티도 나타내는 경우 연속 범위의 시작 및 끝 멤버 만 저장하여 인덱스 집합에 사용 된 공간을 압축 할 수 있습니다. 구현 측면에서 이것은 항목이 범위 제한인지 일반 항목인지를 나타내는 높은 비트로 수행 될 수 있습니다.

이제 인덱스 세트 (따라서 태그에 대한 통계)가 있으면 속성을 먼저 테스트 할 가능성이 없도록 술어를 최적화 할 수 있습니다 (실패한 전략). 이는 T1공통적이며 T2드문 경우 T1 & T2모든 T2인덱스 세트 항목 을 반복 하고에 대한 각 요소를 테스트 하여 술어 를 평가해야 함을 의미합니다 T1.

정렬 된 배열을 사용하여 인덱스 집합을 구현하면 많은 평가 단계를 병합 작업으로 구현할 수 있습니다. T1 & T2수단 우리가 가지고 있는지 T1T2목록, 타겟 어레이가 클수록 입력의 크기를 할당하고 두 입력이 비어있을 때까지 다음의 알고리즘을 수행하는 경우는 T1[0] < T2[0], 다음 T1++(머리 폐기). 만약 T1[0] > T2[0]다음 T2++. 모두 헤드가 동일한 경우, 상기 타겟 어레이를 통해 해당 번호를 복사하고 세 포인터 (증가 T1, T2대상을). 술어가 T1 | T2인 경우 요소는 버리지 않고 작은 요소는 복사됩니다. 형태의 술어는 T1 & ¬T2또한 병합 전략을 사용하여 구현 될 수 있지만, ¬T1또는 T1 | ¬T2할 수 없습니다.

술어 결정 트리를 주문할 때이를 고려해야합니다. 보완은의 RHS &에서 또는 최종 수를 결정하고 실제 요소를 볼 필요가없는 끝에 발생해야합니다 .

인덱스 세트를 사용하지 않으면 각 스레드는 엔티티의 일부를 필터링하여 조건 자와 일치하는 요소 수를 리턴 할 수 있습니다. 인덱스 세트를 사용하면 의사 결정 트리에서 각 스레드에 하나의 노드가 할당됩니다. 순서가 지정된 세트에 해당하는 두 개의 입력 스트림을 사용하고 병합 된 스트림을 리턴합니다. 의사 결정 트리의 각 노드에는 해당 하위 표현식을 수행하는 모든 엔티티를 나타내는 해당 세트가 있으며 세트의 순서로 인해 병합하기 위해 전체 세트를 한 번에 알 필요는 없습니다. .

인덱싱 된 집합 병합 또는 엔터티 목록을 통한 필터링과 같은 다양한 전략을 어느 정도 결합 할 수 있습니다. 필터링은 매우 예측 가능한 성능을 제공합니다. 인덱스 집합을 사용하여 검색 공간을 크게 줄 이도록 쿼리가 매우 구체적이면 병합 작업이 더 나을 수 있습니다. 많은 큰 입력 세트를 병합하면 무차별 검색보다 성능이 훨씬 저하 될 수 있습니다. 최적화 된 알고리즘은 입력 크기, 쿼리 구조 및 통계 지표에 따라 적절한 전략을 선택합니다.

또한, 초기 실행 속도를 높이 지 않더라도 유사한 쿼리가 향후에 실행될 것으로 예상되는 경우 부분 결과를 캐싱하는 것이 유리할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.