Migliore soluzione di Azure per indice di ricerca complesso

0

Devo eseguire ricerche rapide su una combinazione di tag pur includendo intervalli di date:

Esempio:

  • Utenti
    • che hanno richiesto le notifiche
    • che non ha risposto a una notifica inviata almeno 3 giorni fa
    • e a chi non sono state inviate altre notifiche negli ultimi 3 giorni

Struttura dati

La struttura dei dati dell'evento è piuttosto semplice:

  • Evento
    • EntityID
    • EventType
    • EventName
    • Data

Preoccupazioni relative alle prestazioni della struttura del database normalizzate

  • Con miliardi di eventi, la scansione di una tabella non funzionerà
  • L'unica colonna che indicizza bene è Data e non sarà sempre inclusa in ogni filtro
  • EventName non verrà distribuito correttamente per un indice (alcuni nomi di eventi potrebbero includere 1/4 dei record)
  • Fare una semplice query WHERE su questa tabella normalizzata richiederebbe molto probabilmente una scansione completa della tabella che non sarebbe abbastanza veloce

LIKE o ricerca full-text

Un altro approccio consiste nel convertire questi tag in una singola colonna di testo, uno per entità.

  • EntryType_EntryName_Date_Time1, EntryType_EntryName_Date_Time2, EntryType_EntryName_Date_Time3

Quindi, posso eseguire una ricerca full-text SQL.

Questo ridurrebbe il numero di righe di almeno 10 volte, ma non riesco a capire come cercare per intervallo di date:

  • Utente
    • CONTAINS (RequestedNotifications *)
    • NOT CONTAINS (OpenNotification_ID4 *) (Prima di 3 giorni fa ???)
    • NOT CONTAINS (SentNotification *) (Da 3 giorni fa ???)

Al massimo, potrei ridurre la tabella e scansionare una partizione più piccola, ma non credo che possa essere di grande aiuto.

Soluzione in memoria

Ho pensato di creare una macchina virtuale dedicata con una struttura dati in memoria dell'intero set di dati complessi.

Fondamentalmente, vorrei creare un dizionario per ogni tipo di tag con intervalli per intervalli di data e tenere tutto in hashtables per le intersezioni rapide:

// Some structures like these
Dictionary<EventType, Dictionary<EventName, HashSet<int>>> nameIndex;
Dictionary<EventType, Dictionary<EventName, Dictionary<Day, HashSet<int>>>> dayIndex;
Dictionary<EventType, Dictionary<EventName, Dictionary<Day, Dictionary<Hour, HashSet<int>>>>> hourIndex;

// To search like this (kind of)
var entityIds = filters.Select(f => hourIndex[f.tagType][f.tagName][f.day][f.hour])
    .IntersectMultiple()
    .ToList();

// Note: In order to perform an operation like before 3 days
var filterResults = nameIndex[eventType][eventName].except(dayIndex[...][...][today].union(...[today-1]).union(...[today-2]));

Su un server dedicato, potrebbe gestire circa un miliardo di eventi in memoria.

  • Ogni evento richiederebbe ~ 12 byte (~ 4 byte per ciascun indice mantenuto)
  • 1 miliardo di eventi ~ 12 GB di memoria ~ $ 250 / mese A5 VM

Questo potrebbe essere ridimensionato partionando le entità e la persistenza non sarebbe troppo difficile.

Ma prima di intraprendere questo percorso molto personalizzato, vorrei sapere se esiste un modo più semplice per farlo.

Domanda

  • Come posso strutturare un indice in modo che le ricerche rapide possano essere eseguite su più filtri di testo e intervallo di date, come nel mio esempio?
  • Quale soluzione di Azure sarebbe il modo migliore per risolvere questo problema?
posta Rick Love 06.05.2016 - 03:18
fonte

1 risposta

1

Uno dei metodi che ho usato in passato per incrementare enormemente le prestazioni delle query è pre-aggregare i dati lungo uno o più attributi (ad esempio, tipo di evento per giorno, tipo di evento per nome evento, ecc.). Questo sarebbe l'equivalente dell'esecuzione di una somma (per esempio) sui dati dell'ultimo mese e l'archiviazione dei risultati in una tabella separata.

Ciò consentirà di archiviare le transazioni (ciascun record di eventi) in una tabella di backup per quando è necessario visualizzare i dati effettivi, ma consente comunque una ricerca rapida per i dati correnti.

Questa tecnica sembra essere abbastanza comune per la segnalazione.

Probabilmente vorrete aumentare il periodo in cui l'attributo va oltre la cronologia per ridurre al minimo la quantità di dati su cui dovete eseguire una ricerca per intervalli di dati più lunghi. (Potresti aver bisogno dell'aggregazione solo per dati mensili oltre le ultime settimane.)

    
risposta data 10.05.2016 - 06:58
fonte

Leggi altre domande sui tag