Domanda

Quale:

È IL modo consigliato per archiviare data e ora in SQL Server 2008+?

Sono consapevole delle differenze di precisione (e probabilmente di spazio di archiviazione), ma ignorandole per ora, esiste un documento sulle migliori pratiche su quando usare cosa, o forse dovremmo semplicemente usare datetime2 soltanto?

È stato utile?

Soluzione

La documentazione MSDN per datetime consiglia di utilizzare datetime2 . Ecco la loro raccomandazione:

  

Utilizza il time, date, datetime2 e   i tipi di dati per i nuovi datetimeoffset   lavoro. Questi tipi allineano con SQL   Standard. Essi sono più portabile.   time, datetime2 e datetimeoffset   fornire più secondi precisione.   datetimeoffset fornisce fuso orario   sostegno distribuito globalmente   applicazioni.

datetime2 ha grande intervallo di date, una più grande difetto di precisione frazionaria, e la precisione specificata dall'utente opzionale. Anche a seconda della precisione specificata dall'utente può utilizzare meno storage.

Altri suggerimenti

DATETIME2 ha un intervallo di date di "0001/01/01" a "9999/12/31" mentre il tipo DATETIME supporta solo l'anno 1753-9999.

Inoltre, se è necessario, DATETIME2 può essere più precisi in termini di tempo; DATETIME è limitata a 3 1/3 millisecondi, mentre DATETIME2 può essere precisi fino 100ns.

Entrambi i tipi di mappa per System.DateTime in .NET - nessuna differenza c'è

.

Se avete la scelta, mi consiglia di utilizzare DATETIME2 quando possibile. Non vedo alcun beneficio utilizzando DATETIME (tranne che per la compatibilità a ritroso) -. Avrete meno problemi (con date di essere fuori portata e senza problemi del genere)

Inoltre: se avete solo bisogno la data (senza part-time), uso della data - è solo buono come DATETIME2 e consente di risparmiare spazio, anche! :-) Lo stesso vale per solo il tempo - utilizzare TIME. Questo è ciò che questi tipi sono lì per!

datetime2 vince in molti aspetti ad eccezione (app vecchia di compatibilità)

  1. grande intervallo di valori
  2. migliore Precisione
  3. piccolo lo spazio di archiviazione (se non è specificato di precisione specificato dall'utente opzionale)

SQL Data e ora tipi di dati confrontano - datetime, datetime2, data, ora

Si prega di osservare i seguenti punti

  • Syntax
    • datetime2 [(frazioni di secondo di precisione => Guardate sotto formato di immagazzinaggio)]
  • di precisione, scala
    • 0 a 7 cifre, con una precisione di 100 ns.
    • La precisione di default è 7 cifre.
  • dimensione della memoria
    • 6 byte per precisione inferiore a 3;
    • 7 byte per la precisione 3 e 4.
    • Tutti gli altri precisione richiede 8 byte .
  • DateTime2 (3) hanno lo stesso numero di cifre come DateTime ma utilizza 7 byte di memoria invece di 8 byte ( SQLHINTS- DateTime vs dateTime2 )
  • Trova maggiori su datetime2 (Transact-SQL articolo di MSDN)

fonte immagine: MCTS Self-Paced Training Kit (esame 70-432): Microsoft SQL Server® 2008 - implementazione e manutenzione Capitolo 3: Tabelle -> Lezione 1: Creazione di tabelle -> pagina 66

I concurr con @marc_s e @Adam_Poward - DateTime2 è il metodo preferito andare avanti. Ha una gamma più ampia di date, maggiore precisione, e usa uguale o minore di memorizzazione (a seconda della precisione).

Una cosa la discussione mancava, però ...
@Marc_s afferma: Both types map to System.DateTime in .NET - no difference there. Questo è corretto, tuttavia, l'inverso non è vero ... ed è importante quando facendo ricerche intervallo di date (ad esempio, "mi trovi tutti i record modificati su 5/5/2010").

La versione di .NET di Datetime ha gamma simile e precisione a DateTime2. Quando la mappatura di un Datetime .net verso il vecchio SQL DateTime un arrotondamento implicito si verifica . Il vecchio DateTime SQL ha una precisione di 3 millisecondi. Ciò significa che 11:59:59.997 è così vicino come si può arrivare alla fine della giornata. Tutto ciò che più alto è arrotondato fino al giorno successivo.

Prova questo:

declare @d1 datetime   = '5/5/2010 23:59:59.999'
declare @d2 datetime2  = '5/5/2010 23:59:59.999'
declare @d3 datetime   = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'

Come evitare questo arrotondamento implicito è un motivo significativo per passare a DateTime2. arrotondamento implicito date provoca chiaramente confusione:

Quasi tutte le risposte e commenti sono stati pesanti i pro ei luce sul Cons. Ecco un riassunto di tutti i pro ei contro finora più alcune Contro cruciali (a # 2 di seguito) che ho visto citato solo una volta o per niente.

  1. PRO:

1.1. Più conforme a ISO (ISO 8601) (anche se non so come questo entra in gioco nella pratica).

1.2. Più gamma (1/1/0001 al 12/31/9999 vs 1/1 / 1753-12 / 31/9999) (anche se il range in più, tutto l'anno prima del 1753, probabilmente non essere utilizzati a meno es., nella storica, astronomico, geologico, ecc apps).

1.3. corrisponde esattamente la gamma di gamma di .NET Tipo DateTime (anche se entrambi convertire avanti e indietro senza codifica speciale, se i valori sono entro la portata e la precisione ad eccezione Con # 2.1 sotto l'errore altrimenti / si verificherà l'arrotondamento del tipo di destinazione).

1.4. Più di precisione (100 nanosecondi aka 0.000,000,1 sec. Contro 3,33 millisecondi aka 0.003,33 sec.) (Anche se la precisione in più non sarà probabilmente utilizzato tranne che per es., In ingegneria / apps scientifiche).

1.5. Quando configurato per simile (come in 1 millisecondo non "stesso" (come in 3,33 millisecondi) come Iman Abidi ha rivendicato) precisione DateTime, utilizza meno spazio (7 contro 8 byte), ma poi di Naturalmente, si sarebbe perdere il beneficio di precisione che è probabilmente uno dei due (l'altra gamma essere) più propagandato anche se probabili benefici non necessari).

  1. CONS:

2.1. Quando si passa un parametro a un SqlCommand .NET, è necessario specificare System.Data.SqlDbType.DateTime2 se si può essere passando un valore di fuori del campo e / o la precisione del Server di SQL DateTime, perché il valore di default per System.Data.SqlDbType.DateTime.

2.2. Non può essere implicitamente / facilmente convertito in un virgola mobile numerica (# di giorni trascorsi min data-ora) il valore per eseguire le seguenti operazioni per / con esso nelle espressioni SQL Server utilizzando i valori e gli operatori numerici:

2.2.1. aggiungere o sottrarre # di giorni o giorni parziali. Nota:. Usando DateAdd Funzione come una soluzione non è banale quando si ha bisogno di prendere in considerazione più, se non tutte le parti del data-ora

2.2.2. prendere la differenza tra i due data-volte ai fini del calcolo di “età”. Nota: Non si può semplicemente utilizzare la funzione DateDiff di SQL Server, invece, perché non calcola age come la maggior parte delle persone che ci si aspetta che, se i due data-volte capita di attraversare un calendario / orologio data-ora di confine delle unità specificate se anche per un piccola frazione di tale unità, che restituisca la differenza come 1 di tale unità vs 0. Ad esempio, il DateDiff in Day di due data-volte solo 1 millisecondo a parte tornerà 1 vs 0 (giorni) se tali data- i tempi sono diversi giorni di calendario (ad esempio “1999-12-31 23: 59: 59,9,999999 millions” e “2000-01-01 00: 00: 00,0000000”). Gli stessi 1 millisecondo differenza di data-volte se spostato in modo che non attraversano un giorno di calendario, restituirà un “DateDiff” in Day di 0 (giorni).

2.2.3. prendere la Avg di data-volte (in un aggregato di query) semplicemente la conversione a “galleggiare” e poi di nuovo a DateTime.

NOTA: Per convertire DateTime2 ad un numerica, devi fare qualcosa di simile al seguente formula che presuppone ancora i valori sono non inferiore al 1970 (il che significa che stai perdendo tutta la gamma più più altri 217 anni. Nota:. potrebbe non essere in grado di regolare semplicemente la formula per consentire la gamma extra perché si può incorrere in problemi di dimensioni numeriche

25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0 - Fonte: “ https : //siderite.blogspot.com/2015/08/how-to-translate-t-sql-datetime2-to.html

Naturalmente, si potrebbe anche Cast a DateTime primo (e, se necessario, di nuovo a DateTime2), ma che ci si perde la precisione e la gamma (tutti prima dell'anno 1753) le prestazioni di DateTime2 vs. DateTime che sono prolly il 2 più grande e anche allo stesso tempo prolly il 2 meno probabilità necessario che pone la domanda perché usarlo quando si perde le implicite conversioni / facile virgola mobile numerica (numero di giorni) per l'aggiunta / sottrazione / "età" (vs. DateDiff) / Avg beneficio Calcoli che è un grande nella mia esperienza.

A proposito, il Avg di data-tempi è (o almeno dovrebbe essere) un importante caso d'uso. a) Oltre uso nell'ottenere durata media quando data più volte (da una base comune data-tempo) sono utilizzati per rappresentare durata (una pratica comune), b) è anche utile per ottenere un cruscotto di tipo statistico su ciò che il data-media ora è nella colonna data-tempo di un intervallo / gruppo di file. c) Uno standard (o almeno dovrebbe essere standard) ad-hoc query per monitorare / risolvere valori di una colonna che potrebbe non essere valida sempre / più e / o potrebbe essere necessario deprecato è quello di elenco per ogni valore di conteggio della presenza e (se presente) il Min, Avg e Max data ora francobolli associata a tale valore.

DateTime2 seminano il terrore, se sei uno sviluppatore di accesso cercando di scrivere Now () per il settore in questione. Appena fatto un Access -> migrazione SQL 2008 R2 e ha messo tutti i campi datetime come DateTime2. Aggiunta di un record con Now () come valore bombardato fuori. E 'stato bene su 1/1/2012 14:53:04, ma non sul 1/10/2012 2:53:04.

Una volta che il carattere ha fatto la differenza. Speranza che aiuta qualcuno.

Ecco un esempio che vi mostrerà le differenze di dimensione della memoria (byte) e la precisione tra smalldatetime, datetime, datetime2 (0), e datetime2 (7):

DECLARE @temp TABLE (
    sdt smalldatetime,
    dt datetime,
    dt20 datetime2(0),
    dt27 datetime2(7)
)

INSERT @temp
SELECT getdate(),getdate(),getdate(),getdate()

SELECT sdt,DATALENGTH(sdt) as sdt_bytes,
    dt,DATALENGTH(dt) as dt_bytes,
    dt20,DATALENGTH(dt20) as dt20_bytes,
    dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp

che restituisce

sdt                  sdt_bytes  dt                       dt_bytes  dt20                 dt20_bytes  dt27                         dt27_bytes
2015-09-11 11:26:00  4          2015-09-11 11:25:42.417  8         2015-09-11 11:25:42  6           2015-09-11 11:25:42.4170000  8

Quindi, se voglio per memorizzare le informazioni verso il basso per il secondo - ma non al millisecondo -. Posso risparmiare 2 byte ciascuno se uso datetime2 (0) al posto di datetime o datetime2 (7)

Interpretazione di stringhe di data in datetime e datetime2 può essere diverso anche, quando si usano le impostazioni DATEFORMAT non statunitensi. Per es.

set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2

Ciò restituisce 2013-05-06 (vale a dire 6 maggio) per datetime, e 2013-06-05 (vale a dire 5 giugno) per datetime2. Tuttavia, con set dateformat a mdy, sia @d e ritorno @d2 2013-06-05.

Il comportamento datetime sembra in contrasto con la MSDN documentazione di SET DATEFORMAT in cui si afferma: Alcuni formati stringhe di caratteri, ad esempio ISO 8601, sono interpretati in modo indipendente dall'impostazione DATEFORMAT . Ovviamente non è vero!

Fino a quando mi è stato morso da questo, ho sempre pensato che le date yyyy-mm-dd sarebbe solo essere gestite a destra, indipendentemente dalle impostazioni di lingua / locale.

mentre c'è un aumento precisione con dataora2, alcuni client non supportano data, tempo, O dataora2 e ti costringono a convertirti in una stringa letterale.Nello specifico, Microsoft menziona i problemi "di livello inferiore" di ODBC, OLE DB, JDBC e SqlClient con questi tipi di dati e ha un grafico mostrando come ciascuno può mappare il tipo.

Se valore compatibilità oltre precisione, uso appuntamento

Vecchio Question ... Ma voglio aggiungere qualcosa non già affermato da qualcuno qui ... (Nota: Questa è la mia propria osservazione, in modo da non richiedere alcun riferimento)

Datetime2 è più veloce quando viene utilizzato in criteri di filtro.

TLDR:

In SQL 2016 ho avuto un tavolo con centinaia di migliaia di righe e una colonna datetime ENTRY_TIME perché è stato necessario per memorizzare l'ora esatta fino a secondi. Durante l'esecuzione di una query complessa con molte raggiunge e una query sub, quando ho usato clausola WHERE come:

WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00'

La query andava bene inizialmente quando ci sono stati centinaia di righe, ma quando il numero di righe è aumentato, la query ha iniziato a dare questo errore:

Execution Timeout Expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.

Ho rimosso la clausola in cui, e inaspettatamente, la query è stata eseguita in 1 sec, anche se ora TUTTE le righe per tutte le date sono stati recuperati. Corro query interna con clausola where, e ci sono voluti 85 secondi, e senza clausola in cui si completa in 0.01 secondi.

mi sono imbattuto in molte discussioni qui per questo problema come filtraggio datetime prestazioni

ho ottimizzato di query un po '. Ma la velocità reale ho ottenuto è stato cambiando la colonna datetime a datetime2.

Ora la stessa query che scaduta prende in precedenza meno di un secondo.

applausi

Secondo questo articolo , se si desidera avere la stessa precisione di DateTime utilizzando DateTime2 è sufficiente utilizzare DateTime2 (3). Questo dovrebbe dare la stessa precisione, occupano uno byte meno, e di fornire una gamma ampliata.

Ho appena ci siamo imbattuti in un altro vantaggio per DATETIME2: evita un bug nel modulo adodbapi Python, che fa saltare in aria se viene passato un valore libreria datetime standard che ha diverse da zero microsecondi per una colonna DATETIME ma funziona bene se la colonna è definito come DATETIME2.

Select ValidUntil + 1
from Documents

È possibile che SQL non funziona con un campo DateTime2. Esso restituisce ed errore "tipo di operando scontro: datetime2 è incompatibile con int"

L'aggiunta di 1 per ottenere il giorno dopo è qualcosa che gli sviluppatori hanno fatto con date da anni. Ora Microsoft ha un super nuovo campo datetime2 che non può gestire questa semplice funzionalità.

"Usiamo questo nuovo tipo che è peggio di quello vecchio", io non la penso così!

Credo DATETIME2 è il modo migliore per conservare il date, perché ha più efficienza rispetto il DATETIME. In SQL Server 2008 è possibile utilizzare DATETIME2, memorizza la data e l'ora, prende 6-8 bytes per memorizzare ed ha una precisione di 100 nanoseconds. Quindi, chi ha bisogno di una maggiore precisione il tempo ci vuole DATETIME2.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top