2013-01-06 22 views
30

La mia app deve essere sincronizzata con altri utenti di app (su dispositivi propri). Voglio anche supportare l'editing offline, che viene sincronizzato con gli altri utenti collaborativi quando l'utente si connette a Internet.Android: utilizzare l'UUID come chiave primaria in SQLite

Quindi l'utente A modifica (mentre è offline) alcuni dati (in altre parole aggiorna le voci del database) o aggiunge nuovi record al database. Quando l'utente A si connette a Internet, tutte le modifiche e i nuovi record vengono consegnati agli altri utenti collaborativi. L'utente B riceverà quindi le modifiche/gli aggiornamenti e potrà inserirli/aggiornarli nel database dei dispositivi locali degli utenti Bs.

Ma devo assicurarmi che gli ID delle voci del database siano univoci lungo l'intero sistema. Quindi ho bisogno di usare qualcosa come UUID.

La mia domanda: è una cattiva idea usare un UUID (String/Varchar) come chiave primaria in una tabella di database sqlite di Android invece di un intero che sarebbe auto incrementato?

Suppongo che ci sarebbero problemi di prestazioni usando stringhe (un UUID ha 36 caratteri) come chiave primaria.

Suppongo che l'indicizzazione degli uuid anziché degli interi richieda più tempo (confronto tra stringa e confronto di interi). Immagino anche che quando utilizzo l'UUID, ogni volta che viene inserito un nuovo record di database/voce, il database deve reindicizzare la colonna della chiave primaria, poiché l'indice della chiave primaria non è più in ordine ordinato (che sarebbe quando userei numero intero incrementa automaticamente la chiave primaria, poiché ogni record futuro viene aggiunto alla fine, perché la nuova chiave primaria incrementata automatica è sempre il numero più grande finora, quindi l'indice sarà automaticamente nell'ordine ordinato). Quello che devo anche fare è partecipare su 2 - 3 tavoli. Immagino anche che confrontare le stringhe su JOINS anziché integer rallenti la query del database.

Tuttavia non vedo alcuna altra possibilità per implementare un tale sistema di sincronizzazione collaborativo, quindi devo usare UUID, giusto?

Un'altra possibilità sarebbe utilizzare una chiave primaria di incremento automatico intero e utilizzare una seconda colonna uuid. Quindi, per lavorare sul dispositivo locale degli utenti, utilizzerei questa chiave primaria (numero intero) per JOIN ecc., Mentre userei la colonna uuid per la sincronizzazione con gli altri utenti.

Cosa ne pensate di questo approccio o secondo voi è molto utile, dal momento che non ci si aspetta un grosso problema di prestazioni se si utilizza l'UUID direttamente come chiave primaria?

Altri suggerimenti?

risposta

27

È una cattiva idea utilizzare un UUID (String/Varchar) come chiave primaria in una tabella di database sqlite di Android invece di un numero intero che verrà incrementato automaticamente?

L'unico problema per-certo che mi viene in mente è che non sarà in grado di utilizzare CursorAdapter e le sue sottoclassi per la visualizzazione dei risultati delle query su quel tavolo. CursorAdapter richiede un numero intero unico _id nella colonna Cursor e presumibilmente non ne avrai uno. Dovresti creare il tuo adattatore, magari estendendo BaseAdapter, che lo gestisce.

Suppongo che ci sarebbero problemi di prestazioni usando stringhe (un UUID ha 36 caratteri) come chiave primaria.

Forse, ma sarei un po 'sorpreso se si trasforma in un problema materiale su database di dimensioni del dispositivo.

Tuttavia non vedo alcuna altra possibilità per implementare un tale sistema di sincronizzazione collaborativo, quindi devo usare UUID, giusto?

È necessaria una sorta di UUID per il proprio protocollo di rete. Presumibilmente, avrai bisogno di quell'UUID nel tuo database. Se quell'UUID deve essere la chiave primaria di un tavolo, non posso dire, perché non conosco il tuo schema.

Un'altra possibilità sarebbe quella di utilizzare una chiave primaria di incremento automatico intero e utilizzare una seconda colonna uuid. Quindi, per lavorare sul dispositivo locale degli utenti, utilizzerei questa chiave primaria (numero intero) per JOIN ecc., Mentre userei la colonna uuid per la sincronizzazione con gli altri utenti.

Corretto. Dovresti avere una UUID-> tabella di mapping degli ID interi locali, utilizzare gli UUID nel tuo protocollo di rete e mantenere il database locale principalmente usando gli ID interi locali. Non posso dire se questo sarà un miglioramento significativo delle prestazioni (in particolare data la maggiore complessità dello schema del database).

Cosa ne pensate di questo approccio o secondo voi è molto utile, dal momento che non ci si aspetta un grosso problema di prestazioni se si utilizza l'UUID direttamente come chiave primaria?

IMHO, eseguire alcuni test delle prestazioni in modo da ottenere alcuni dati concreti confrontabili o preoccuparsi solo se l'I/O del database sembra lento.

+0

È possibile archiviare UUID come binario a 16 byte –

+0

@EirNym: È bello sapere, anche se non riesco a vedere cosa ha a che fare con la domanda, la risposta o l'apparente svalutazione della mia risposta. – CommonsWare

+0

si dice che la rappresentazione ASCII è solo uno per UUID in SQLite3, e indicare gli svantaggi per questo. La rappresentazione binaria non presenta tali inconvenienti: è abbastanza veloce per i dispositivi con Android 2.3+ che è stato raccomandato minimo a quell'anno 2013. Oggi abbiamo dispositivi più veloci e possiamo usare non solo SQLite3 come motore di database, mentre rimarrà comune. –

2

Una serie di risultati di performance per UUID come binario e il testo può essere trovato in qualche modo connessa questione UUID/SQLite: https://stackoverflow.com/a/11337522/3103448

Per i risultati, sia UUID binari e di stringa può essere efficace nel SQLite per creare e query quando indicizzato. Un compromesso separato è se una stringa leggibile dall'uomo è preferita alla dimensione dei dati più piccola delle dimensioni del file binario.

Problemi correlati