2010-01-21 19 views
8

Memorizzo i valori datetime in un database SQLite (utilizzando Delphi e la libreria DISqlite). La natura del db è tale che non avrà mai bisogno di essere trasferita tra computer o sistemi, quindi l'interoperabilità non è un vincolo. La mia attenzione è invece sulla velocità di lettura. Il campo datetime verrà indicizzato e cercherò molto su di esso, oltre a leggere in migliaia di valori datetime in sequenza.Modo ottimale per archiviare valori datetime nel database SQLite (Delphi)

Dato che SQLite non ha un tipo di dati esplicito per i valori datetime, ci sono diverse opzioni:

  • uso tipo di dati REAL e valori TDateTime negozio di Delphi direttamente: più veloce, nessuna conversione da stringa su carico; impossibile eseguire il debug delle date utilizzando un gestore db come SQLiteSpy, poiché le date non saranno leggibili. Impossibile utilizzare le funzioni di data SQLite (?)

  • utilizzare un formato stringa semplice, ad es. YYYYMMDDHHNNSS: la conversione è richiesta ma relativamente facile sulla CPU (non è necessario cercare i separatori), i dati sono leggibili. Non è ancora possibile utilizzare le funzioni di data SQLite.

  • fare qualcos'altro. Qual è la cosa consigliata da fare?

Ho letto http://www.sqlite.org/lang_datefunc.html ma non c'è menzione di quale tipo di dati da utilizzare, e, non essendo formalmente istruito nella programmazione, non abbastanza Grok l'attenzione sulla data di Julian. Perché la conversione aggiuntiva? Leggerò molto in questi valori, quindi eventuali conversioni aggiuntive tra stringhe e TDateTime aggiungono un costo significativo.

+0

Ho anche visto http://stackoverflow.com/questions/1933720/how-do-i-insert-datetime-value-into-a-sqlite-database ma non risponde alla mia domanda su cosa il modo ottimale è, o c'è un motivo davvero convincente per preferire il formato di stringa ISO (e le conversioni associate) oltre l'inserimento diretto dei valori di TDateTime di Delphi. –

risposta

8

È possibile utilizzare uno dei formati di stringa supportati da SQLite, ad es. YYYY-MM-DD HH:MM:SS.SSS.

Sarebbe altrettanto semplice come YYYYMMDDHHNNSS - non avresti ancora bisogno di scansionare i separatori, dato che tutti i numeri sono di lunghezza fissa - e si otterrebbe il supporto della funzione data SQLite.

Se è necessario il supporto della funzione di data SQLite, sceglierei questo metodo.

In caso contrario, si consiglia di utilizzare i valori REAL. È ancora possibile confrontarli tra loro (i numeri più alti sono più avanti nel tempo) e considerare separatamente la data e l'ora (prima e dopo il punto decimale, rispettivamente) senza eseguire la conversione in TDateTime.

+0

Ho usato questa soluzione ASCII pesantemente, con CSV e altri database, ed è quello che vorrei fare. Inoltre funzionano le funzioni di data SQLite. Vinci vincere. –

5

Un compromesso sarebbe quello di attenersi ai valori REAL, ma memorizzarli come date julian usando DateTimeToJulianDate di Delphi. In questo modo rimangono veloci per la lettura, ci sono poche prestazioni perse nella conversione e sono ancora in un formato che ha senso al di fuori di Delphi.

+0

Ho usato valori REAL prima, uno svantaggio è che i valori nel DB non sono ** leggibili **, e questo è scomodo quando si esegue il debug/analizzando usando uno strumento SQL. –

2

Per questo, di solito utilizzo un tipo di dati Integer e memorizza il valore di timestamp Unix allo stesso modo (per esempio, eq # da 1-1-2000). Calcolare questo t/da un TDateTime equivale a moltiplicare/immergersi con/per 86400 e aggiungere una costante per "since".

Se è necessaria maggiore precisione È possibile utilizzare DateTime come FILETIME (ad es. Int64) con incrementi di 100 ns. Ci sono routine di conversione in SysUtils per questo e il tuo timestamp è memorizzato in UTC.

0

Se la vostra preoccupazione è solo un formato leggibile a livello di database, è possibile memorizzare due campi separati, ad esempio:

DELPHI_DATE REAL (DOPPIO, se possibile, ma non so SQLite), indicizzati . Tutte le query e i confronti programmatici dovrebbero utilizzare questo campo.

HUMAN_READABLE_DATE Varchar (23) con il formato 'AAAA-MM-GG HH: MM: SS.SSS'. Forse indicizzato (se davvero necessario). La maggior parte delle query di input umano dovrebbe includere questo campo ed è possibile utilizzare (come detto da altri) le funzioni di data SQLite.

ha alcuni svantaggi: il consumo

  • spazio database e il traffico di rete cresce,
  • operazioni di inserimento vorrà un po 'di più perché la conversione necessaria,
  • alcuna sincronizzazione automatica tra valori se aggiornati al di fuori programma

Se è adatto per le vostre esigenze particolari, dipende da voi.

0

Non so se questa risposta è applicabile alla libreria DISqlite ma ...
Di seguito è riportato un codice che illustra ciò che funziona per me utilizzando sia Delphi 2010 che il wrapper SQLite3 di Tim Anderson.

SQL per creare campo:

sSQL := 'CREATE TABLE [someTable] (' + 
      ' [somefield1] VARCHAR(12),' + 
      ' [somefield2] VARCHAR(12),' + 
      ' [myDateTime] DATETIME);'; 

SQL per popolare campo:

sSQL := 'INSERT INTO someTable(somefield1, somefield2, myDateTime)' + 
     ' VALUES ("baloney1", "baloney2","' + FloatToStr(Now) + '");'; 

Esempio di recupero dei dati dal campo:

var 
sDBFilePathString: string; 
sl3tbl: TSqliteTable; 
fsldb : TSQLiteDatabase; 
FromdbDTField : TDateTime; 

begin 
    ... 
    ... 
    fsldb := TSQLiteDatabase.Create(sDBFilePathString); 
    sl3tbl := fsldb.GetTable('SELECT * FROM someTable'); 
    FromdbDateTime := StrToFloat(sl3tbl.FieldAsString(sl3tbl.FieldIndex['myDateTime'])); 
    Showmessage('DT: ' + DateTimeToStr(FromdbDTField)); 
end; 

Risultato:

**DT: 10/10/2013 1:09:53 AM** 

Come ho accennato sulla prima riga - non so se questo funzionerà con la libreria DISqlite ma se lo fa è un modo abbastanza pulito di gestire le cose. Ti lascio a te per rendere le cose più belle o più eleganti.

Problemi correlati