Struttura dei dati che consente ricerche efficienti basate su tag


11

Sto cercando una struttura di dati altamente efficiente per l'archiviazione di dati simile al seguente.

ID tag Ordine1 Ordine2 
--------------------------
1 1,2 1 1
2 2,5 2 3
3 1,7 4 7
4 6 3 0

Ho bisogno di essere in grado di interrogare questa struttura nel modo un che mi avrebbe dato una lista di tutti gli ID che contengono l'espressione di tag - sostenere ANDed ORe NOToperazioni. Per esempio. ((1 o 2) e non 7)

Devo anche essere in grado di specificare l'ordine dei risultati (Ordine1 o Ordine2) ed essere in grado di specificare il numero massimo di righe restituite con un offset opzionale. Le prestazioni per il recupero dei primi 30-100 risultati sono fondamentali.

Infine, ho bisogno di un modo economico per cercare "relazioni tag", ad esempio voglio sapere quali tag "si collegano" ai tag (1 OR 2) e con quale frequenza. Significa quali tag compaiono nello stesso set di 1 OR 2 ... ordinati per frequenza.

Qualche idea di quale struttura di dati (o insieme di strutture) sarebbe altamente efficiente per questo tipo di lavoro?

(Vorrei usarlo come prova di concetto per riprogettare le pagine taggate della famiglia di siti SE)


1
Solo un commento (forse banale). Perché non fare affidamento su un sistema di gestione di database relazionali? È possibile definire una tabella con le coppie <id, tag> e aggiungere un indice nella colonna tag. Quindi è possibile utilizzare query SQL standard per l'estrazione di dati. RDBMS eseguirà in modo efficiente il lavoro "sporco" di ottimizzazione delle query e ordinamento dei risultati.
Marzio De Biasi,

@Vor, le espressioni sono incredibilmente inefficienti su larga scala, i self-join diventano query da incubo.
Sam Saffron,

@ Sam: ok. Il tuo compito è abbastanza comune, quindi ho pensato che un buon RDBMS (con uno strumento di data mining) potesse fare il lavoro. Lascio la parola a un esperto di strutture dati. :-)
Marzio De Biasi

Credo che consentire tutte le combinazioni di AND, OR, NOT renderà difficile la creazione di una struttura di dati che non elenca tutti gli elementi (forse potrebbe essere limitata a 3-CNF?). Se non esiste tale limitazione, forse basta scorrere i record (nell'ordine specificato) fino a trovare 30-100 che soddisfano i requisiti del tag. Anche se, in generale, sono d'accordo con il suggerimento di Vor di utilizzare un database per fare il lavoro pesante per te.
Bbejot,

Non sono un esperto, ma penso che se non imposti alcune restrizioni sul modo in cui puoi chiedere i tag, sarà difficile. Limitarli ai CNF (come suggerito da bbejot) è un modo, un altro sta restringendo il numero di tag diversi che la query può richiedere con un piccolo numero (diciamo 6).
Kaveh,

Risposte:


6

Questa non è esattamente la risposta di un'efficiente struttura di dati, ma piuttosto un'elaborazione sui commenti di @bbejot e @Kaveh che danno un argomento agitando la mano sul perché, vista la domanda attuale, non dovremmo aspettarci qualcosa che fa molto meglio della ricerca nel intero database. L'argomento si basa su una riduzione da SAT, l' ipotesi del tempo esponenziale e un sacco di agitando la mano.

Supponiamo di avere fino a tag diversi, quindi possiamo pensare a ciascun id come associato a un bitvector x di lunghezza | x | = n dove x j = 1 se abbiamo il tag j -th e x j = 0 altrimenti. Dal momento che non ci sono restrizioni reali sull'aspetto del database, posso presumere che abbia id da 1 a 2 n con k -th id con un vettore tag associato di knX|X|=nXj=1jXj=012nKKscritto in binario. I campi dell'ordine possono essere arbitrari, poiché rendono solo più difficile il problema. Ora, se ci viene data una query arbitraria di , O R e N O T , allora questo sta solo ponendo una domanda SAT su n variabili. Secondo l'ipotesi del tempo esponenziale, non possiamo aspettarci che questo sia molto più veloce di 2 n ... o in altre parole, non possiamo aspettarci che sia molto più veloce della ricerca nell'intero database.UNNDORNOTn2n

Non dovremmo aspettarci una ricerca efficiente nella lunghezza della query (mediante riduzione a SAT). Inoltre, non dovremmo aspettarci molto meglio che guardare tutti gli elementi nel database dall'ipotesi del tempo esponenziale.

Per sperare in una struttura dati efficiente per questa domanda, dovremo fare alcune ipotesi serie sulla struttura del database che non sono state fatte in questa domanda. Ad esempio, se assumiamo una struttura speciale sulle query (come CNF), possiamo sperare in qualcosa di più efficiente. Un'ipotesi alternativa è sulla struttura del database. Probabilmente potremmo presumere che dati tag, solo una piccola parte dei tag sarà presente su un dato id (diciamo logaritmicamente pochi 1 s). Questo non è un presupposto irragionevole data l'applicazione di domande taggate (a che cosa servono i tag se quasi ogni singolo tag viene utilizzato per una domanda).n1


Buona osservazione. Ogni domanda ha al massimo 5 tag, quindi una query sui tag equivale a un 5-CNF.
Kaveh

grazie! sì, possiamo ipotizzare un ulteriore 5-CNF qui, il comportamento di tagging non è casuale. In generale la gente taggerà le cose con i tag più comuni, in modo da consentire alcune altre scorciatoie.
Sam Saffron,

1
@Kaveh, abbiamo finito col creare una struttura di memoria. Esistono alcune scorciatoie non banali, l'ordinamento è un collo di bottiglia, l'uso dell'ordinamento heap o un ordinamento rapido modificato consente di selezionare in modo efficiente la N superiore senza dover eseguire un ordinamento completo. i calcoli pre-calcolati ti consentono di selezionare i perni in modo più efficiente ed evitarli quando è necessaria una scansione completa. il multithreading accelera le selezioni. molto lavoro può essere rinviato in background prima che gli utenti interagiscano con le strutture. sorprendentemente, le nostre strutture in memoria hanno una media di 0 ms per una ricerca nel set di dati di overflow dello stack.
Sam Saffron,

@SamSaffron - Dov'è il post MSO che descrive in dettaglio questa funzione? Abbiamo una segnalazione di bug qui .
Kevin Vermeer,

5

Questa è una risposta piuttosto semplice, ma penso efficace:

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

Map Id (Set Tag)IdO(n*log(m))


Tendo a concordare sul fatto che alcune strutture molto semplici come una mappa avvolta più volte potrebbero essere il modo migliore per andare qui. la memoria è economica e il mantenimento di più cache non è troppo difficile
Sam Saffron,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.