Estrutura de dados que permite pesquisas eficientes baseadas em tags

11

Estou procurando uma estrutura de dados altamente eficiente para armazenamento de dados semelhante à seguinte.

Tags de identificação Pedido1 Pedido2 
--------------------------
1 1,2 1 1
2 2,5 2 3
3 1,7 4 7
4 6 3 0

Eu preciso ser capaz de consultar essa estrutura de tal forma a que ele iria me dar uma lista de todos os ids contendo uma expressão de marcas - apoiar ANDe ORe NOToperações. Por exemplo. ((1 ou 2) e não 7)

Também preciso especificar a ordem dos resultados (Pedido1 ou Pedido2) e especificar o máximo de linhas retornadas com um deslocamento opcional. O desempenho para a busca dos primeiros 30-100 resultados é fundamental.

Por fim, preciso de uma maneira barata de pesquisar "relações de tags". Por exemplo, quero saber quais tags "se relacionam" com tags (1 OU 2) e com que frequência. Significado de quais tags aparecem no mesmo conjunto que 1 OU 2 ... ordenadas por frequência.

Alguma idéia de que estrutura de dados (ou conjunto de estruturas) seria altamente eficiente para esse tipo de trabalho?

(Gostaria de usar isso como uma prova de conceito para redesenhar as páginas marcadas da família de sites SE)

Sam Saffron
fonte
1
Apenas um comentário (talvez trivial). Por que você não confia em um sistema de gerenciamento de banco de dados relacional? Você pode definir uma tabela com os pares <id, tag> e adicionar um índice na coluna de tags. Em seguida, você pode usar consultas SQL padrão para extrair dados. O RDBMS fará com eficiência o trabalho "sujo" de otimização de consulta e classificação de saída.
Marzio De Biasi
@Vor, as expressões são incrivelmente ineficientes em alta escala, as junções automáticas tornam-se consultas de pesadelo.
Sam Saffron
@ Sam: ok. Sua tarefa é bastante comum, então pensei que um bom RDBMS (com uma ferramenta de mineração de dados) poderia fazer o trabalho. Deixo a palavra a um especialista em estrutura de dados. :-)
Marzio De Biasi
Eu acredito que permitir todas as combinações de AND, OR, NOT dificultará a criação de uma estrutura de dados que não seja listada em todos os itens (talvez possa ser limitado a 3-CNF?). Se essa limitação não existir, talvez apenas execute os registros (na ordem especificada) até encontrar 30-100 que atendem aos requisitos de sua tag. Embora, em geral, eu concorde com a sugestão de Vor de usar um banco de dados para fazer o trabalho pesado para você.
bbejot 5/05
Não é um especialista, mas acho que se você não colocar algumas restrições na maneira de perguntar sobre tags, será difícil. Limitá-los a CNFs (como bbejot sugeriu) é uma maneira, outra está restringindo o número de tags diferentes que as consultas podem perguntar por um número pequeno (por exemplo, 6).
Kaveh

Respostas:

6

Esta não é exatamente uma resposta de uma estrutura de dados eficiente, mas sim uma elaboração dos comentários de @bbejot e @Kaveh, dando um argumento de ondulação para saber por que, dada a pergunta atual, não devemos esperar algo que seja muito melhor do que pesquisar no banco de dados inteiro. O argumento é baseado em uma redução do SAT, na hipótese do tempo exponencial e em muitas atividades manuais.

nx|x|=nxj=1jxj=012nkkANDORNOTn2n

Não devemos esperar uma pesquisa eficiente no comprimento da consulta (por redução para SAT). Também não devemos esperar muito melhor do que olhar para todos os itens no banco de dados pela hipótese de tempo exponencial.

n1

Artem Kaznatcheev
fonte
Boa observação. Cada pergunta tem no máximo 5 tags, portanto, uma consulta sobre tags é equivalente a um 5-CNF.
Kaveh
obrigado! sim, podemos assumir mais 5-CNF aqui, o comportamento da marcação não é aleatório. Em geral, as pessoas marcam as coisas com as tags mais comuns, o que permitirá outros atalhos.
Sam Saffron
1
@ Kaveh, acabamos lançando uma estrutura de memória. Existem alguns atalhos não triviais, a classificação é um gargalo, o uso da classificação de heap ou uma classificação rápida modificada permite selecionar com eficiência o N superior, sem a necessidade de executar uma classificação completa. o pré-cálculo de classificações permite escolher pivôs com mais eficiência e evitar classificações quando uma varredura completa é necessária. o multithreading acelera as seleções. muito trabalho pode ser adiado para segundo plano antes que os usuários interajam com as estruturas. surpreendentemente, nossas estruturas na memória estão em média 0ms para uma pesquisa no conjunto de dados de estouro de pilha.
Sam Saffron
@SamSaffron - Onde está o post do MSO detalhando esse recurso? Temos um relatório de erro aqui .
Kevin Vermeer
5

Esta é uma resposta bastante direta, mas acho eficaz:

Map Tag ([Id],[Id])O(log(n))

Map Id (Set Tag)IdO(nlog(m))

sclv
fonte
Estou tendendo a concordar que algumas estruturas muito simples, como um mapa em spool várias vezes, podem ser o melhor caminho a percorrer aqui. memória é barato e manutenção de vários caches não é muito difícil
Sam Saffron