2011-09-07 8 views
13

Ho una tabella di Azure in cui i clienti postano messaggi, potrebbero esserci milioni di messaggi in una singola tabella. Voglio trovare il modo più veloce per ottenere i messaggi inviati negli ultimi 10 minuti (che è la frequenza con cui aggiorno la pagina web). Poiché solo la chiave della partizione è indicizzata, ho giocato con l'idea di utilizzare la data & in cui il messaggio è stato pubblicato come chiave di partizione, ad esempio una stringa come un formato di data ISO8601 come "2009-06-15T13: 45: 30.0900000"Il modo più veloce di interrogare gli ultimi articoli in una tabella di Azure?

Esempio pseudo codice:

var message = "Hello word!"; 
var messagePartitionKey = DateTime.Now.ToString("o"); 
var messageEntity = new MessageEntity(messagePartitionKey, message); 
dataSource.Insert(messageEntity); 

, e poi interrogare per i messaggi inseriti negli ultimi 10 minuti come questo (non testata pseudo codice di nuovo):

// Get the date and time 10 minutes ago 
var tenMinutesAgo = DateTime.Now.Subtract(new TimeSpan(0, 10, 0)).ToString("o"); 

// Query for the latest messages 
var latestMessages = (from t in 
    context.Messages 
    where t.PartitionKey.CompareTo(tenMinutesAgo) <= 0 
    select t 
    ) 

Ma questo sarà preso bene da l'indice? O causerà una scansione completa della tabella? Qualcuno ha un'idea migliore di fare questo? So che c'è un timestamp su ogni oggetto della tabella, ma non è indicizzato, quindi sarà troppo lento per il mio scopo.

+0

Come sidenote, dovresti probabilmente usare qualcosa di più generale come chiave di partizione. Mi piace dove il tuo post appartiene o così. Dai un'occhiata a http://msdn.microsoft.com/en-us/library/windowsazure/hh508997.aspx –

+0

La stessa macchina fa sia gli inserti che la query? In caso contrario, è necessario tenere conto del potenziale disallineamento dell'orologio tra i client. I tick di –

risposta

5

Penso che tu abbia la giusta idea di base. La query che hai progettato dovrebbe essere efficiente quanto potresti sperare. Ma ci sono alcuni miglioramenti che potrei offrire.

Invece di utilizzare DateTime.Now, utilizzare Date.UtcNow. Da quello che ho capito, le istanze sono impostate per utilizzare Utc time come base, comunque, ma questo assicura solo che tu stia confrontando le mele con le mele e puoi convertire il tempo indietro in qualsiasi fuso orario che desideri durante la visualizzazione.

Anziché memorizzare l'ora come .ToString("o") trasformare il tempo in tick e archiviarlo, si finirà con meno problemi di formattazione (a volte si otterrà la specifica del fuso orario alla fine, a volte no). Inoltre, se vuoi sempre vedere questi messaggi ordinati dal più recente al più vecchio, puoi sottrarre il numero di tick dal numero massimo di tick, ad es.

var messagePartitionKey = (DateTime.MaxValue.Ticks - _contactDate.Ticks).ToString("d19"); 

Sarebbe anche una buona idea specificare un tasto di riga. Mentre è altamente improbabile che due messaggi vengano pubblicati esattamente nello stesso momento, non è impossibile. Se non si dispone di un tasto di riga evidente, è sufficiente impostarlo come guida.

+0

saranno univoci per ogni record e creeranno una singola partizione per ogni chiave di partizione. Non penso che prendere le zecche sia una buona idea. – Kurkula

+1

Sì, questo creerà una partizione per ogni riga, ma in questa situazione non vi è alcuno svantaggio nel farlo. – knightpfhor

+0

Non sono sicuro, ma la creazione di più partizioni ridurrà le prestazioni. – Kurkula

3

Suggerirei di fare qualcosa di simile a ciò che l'API Diagnostics sta facendo con WADPerformanceCountersTable. There PartitionKey raggruppa un numero di timestamp in un singolo elemento. Vale a dire: arrotonda tutti i timestamp in pochi minuti (ad esempio, i 5 minuti più vicini). In questo modo non hai una quantità limitata di chiavi di partizione e tuttavia riesci ancora a eseguire query a distanza su di esse.

Così, per esempio, si può avere un PartitionKey che mappa ad ogni timestamp che viene arrotondato in 00:00, 00:05, 00:10, 00:15, ecc .. e poi convertito in zecche

+0

Sembra un'ottima alternativa, ma nel mio scenario la pagina viene aggiornata a intervalli diversi da molti client. Non so mai quando arriva la richiesta e non posso rischiare di inviare gli stessi o troppo pochi messaggi al client. –

+0

Mi piace questa idea. – Roboblob

4

La chiave primaria per tabella è la combinazione di PartitionKey e RowKey (che forma un indice cluster).

Nel tuo caso, vai su RowKey invece di ParitionKey (fornisci un valore costante per questo).

È anche possibile seguire l'approccio Diagnostica, come per ogni dieci minuti creare una nuova chiave di partizione. Ma questo approccio è principalmente per esigenze come Archieving/Purging, ecc.,

0
  • Dalla mia comprensione utilizzando chiave di partizione con uguale "=" sarà molto più veloce di meno che utilizzando "<" o "maggiore di">.
  • Assicurati anche di fare più sforzi se riusciamo a ottenere la combinazione unica di chiave di partizione e chiave di riga per la tua condizione.
  • Assicuratevi inoltre di fare meno combinazioni univoche dei valori delle chiavi di partizione per evitare più partizioni.
Problemi correlati