2010-07-31 6 views
3

J'expérimente avec un programme qui insère des données dans une base de données SQL 2005 Server (sur XP SP3) à haut débit. (Ceci est pour collecter des données de synchronisation afin que je puisse évaluer différents aspects de ma conception).Précision de SQL Getdate?

Mon configuration de base consiste à insérer une donnée dans un tableau comme suit (et en utilisant un SP qui spécifie que le champ de charge utile):

create table data 
(
Id int PRIMARY KEY Identity, 
payload datatime not null, 
inserted datetime default (getdate()) not null 
) 

Notez que les deux champs datetime ont UNIQUE sur eux aussi .

Sur le programme client, j'appelais le SP dans une boucle tellement serrée que j'avais des problèmes avec la précision de la valeur .Net DateTime.Now (et éventuellement du thread dormant) et donc violant la contrainte unique de la charge utile. Je ai adressé par une combinaison d'une variable chronomètre, un peu de Thread.Sleep() et la construction manuelle des données "payload" de sorte qu'il n'a pas violé la résolution du champ SQL DateTime (3.3 mS)

Cependant avec les inserts étant générés à une vitesse comprise entre 5mS et 10mS J'ai commencé à voir des problèmes avec le champ "Inséré" du côté SQL où une ligne est régulièrement rejetée pour une violation de clé unique. Ce n'est que lorsque je ralentis mon taux d'insertion à plus de 15 mS que ces problèmes disparaissent. Ce taux ressemble étrangement au problème de précision que j'avais avec le .Net DateTime.Now (j'ai lu 16mS sur un post quelque part) donc je me demande quelle est la précision réelle de la fonction SQL Getdate().

Alors, quelqu'un peut-il me dire ce qui soutient GetDate(), et serait-il lié à la même source que la valeur .Net DateTime.Now? Et quelle précision dois-je en attendre? En outre, je connais le type DATETIME2 dans le serveur SQL 2008, ce qui soulève la question de savoir quelle est la précision de GetDate() dans ce système également.

+0

Pourquoi avez-vous besoin d'une contrainte unique sur la colonne insérée? La colonne d'identité montrera dans quel ordre ils ont été insérés.Je présume que la base de données générée sera sensible aux variations naturelles de la fréquence avec laquelle elle peut traiter vos demandes d'insertion en raison d'une activité simultanée, si l'insertion précédente a causé une division de page etc. de toute façon, elle n'a aucun sens sémantique justifier le contraignant comme ça. –

+0

@martin .. L'unicité et l'ordre ne sont pas la même chose. Je barbotais avec l'idée que vous ne pouviez pas insérer deux rangées en même temps - mais la précision du getdate m'a prouvé le contraire. Cependant, je ne dis pas que ce que je fais est la chose la plus intelligente au monde! –

Répondre

1

DATETIME est stocké sous forme de 2 entiers. L'une représentant la partie date et l'autre la partie temps (nombre de graduations après minuit) cochent chacune is 1/300 of a second pour avoir au moins une précision théorique de 3,3 millisecondes.

Je viens d'essayer d'exécuter ce sur ma machine

declare @d varchar(24) 

while 1=1 
begin 
set @d=CONVERT(VARCHAR(24), GETDATE(), 113) 
raiserror('%s',0,1, @d) with nowait 
end 

Et a obtenu une course assez longue où il a fait monter d'un tic à la fois, donc je ne pense pas qu'il y ait une limitation inhérente qui empêche réaliser cela.

01 Aug 2010 00:56:53:913 
... 
01 Aug 2010 00:56:53:913 
01 Aug 2010 00:56:53:917 
... 
01 Aug 2010 00:56:53:917 
01 Aug 2010 00:56:53:920 
... 
01 Aug 2010 00:56:53:920 
01 Aug 2010 00:56:53:923 

En ce qui concerne votre question au sujet GetDate() précision dans SQL Server 2008, c'est le même que pour SQL2005. sysdatetime est destiné à avoir une plus grande précision. J'ai juste essayé de courir le suivant et ai été surpris par l'écart entre les deux résultats.

SET NOCOUNT ON 

CREATE TABLE #DT2(
[D1] [datetime2](7) DEFAULT (getdate()),  
[D2] [datetime2](7) DEFAULT (sysdatetime()) 
) 
GO 

INSERT INTO #DT2 
      DEFAULT VALUES 
GO 100 

SELECT DISTINCT [D1],[D2],DATEDIFF(MICROSECOND, [D1], [D2]) AS MS 
FROM #DT2 

Résultats

D1       D2        MS 
---------------------------- -----------------------  ------ 
2010-08-01 18:45:26.0570000 2010-08-01 18:45:26.0625000  5500 
2010-08-01 18:45:26.0600000 2010-08-01 18:45:26.0625000  2500 
2010-08-01 18:45:26.0630000 2010-08-01 18:45:26.0625000  -500 
2010-08-01 18:45:26.0630000 2010-08-01 18:45:26.0781250  15125 
2010-08-01 18:45:26.0670000 2010-08-01 18:45:26.0781250  11125 
2010-08-01 18:45:26.0700000 2010-08-01 18:45:26.0781250  8125 
+0

L'écart n'est pas déraisonnable car les temporisateurs ne s'arrêtent pas lorsque les données sont insérées dans les tables. J'ai vu sur cette http://msdn.microsoft.com/en-us/library/ms188383.aspx page MS qu'ils ont mentionné cela lors de la démonstration d'un "select Getdate(), sysdatetime()". Cependant, mon problème semble tourner autour de getdate() sur ma machine ne renvoyant que des valeurs datetime avec une granularité d'environ 15 mS. Je vais lancer vos requêtes plus tard et voir ce qu'elles ressortent sur ma machine. BTW quel matériel et OS exécutez-vous? –

+0

Je viens de jeter un autre coup d'oeil à vos résultats et il semble qu'il y ait des choses étranges qui se passent pendant les insertions. Je peux gérer D1! = D2 sur une seule ligne, mais toutes ces valeurs D2 sont supérieures à celles de D1 les lignes sont vraiment intéressantes (ou effrayantes). Doit être une sorte de problème de threads étrange –

+0

@Peter - RE: Spécifications qui était juste sur mon ordinateur de bureau alors XP, 2 Go de RAM charge probablement de l'activité simultanée à partir d'autres applications, mais il n'a pas de sens comment la version GetDate n'a pas arriver à '26.07' bien après que sysdatetime ait signalé 26.078. Chaque insertion est dans sa propre transaction et devrait donc avoir été validée avant de commencer la suivante. –

2

DATETIME a une précision de 3,3ms, mais GETDATE() ne retourne pas à ce moment précis que vous avez découvert. Consultez le MSDN page for date/time types/functions pour plus d'informations sur le fonctionnement des nouveaux types/fonctions.

+1

Je ne suis pas d'accord sur la terminologie. La résolution est de 3.3mS mais la précision ne l'est pas! Et j'ai vu cette page qui a la phrase clé "Toutes les valeurs de date et d'heure système sont dérivées du système d'exploitation de l'ordinateur sur lequel l'instance de SQL Server est en cours d'exécution." ce qui ne dit pas comment ils sont dérivés! –

+0

DATETIME a une précision de 3.3ms (ou environ) - et est précis à 3.3ms si vous l'avez défini à partir d'une horloge atomique. :) C'est GETDATE() qui est le problème ici, pas DATETIME. La résolution est un terme plus agréable, tho '. –

+0

. Étant donné que getdate retourne un datetime, ils sont en quelque sorte entrelacés .. mais oui, je sais que GetDate est le problème ici .. consultez également http://www.tutelman.com/golf/measure/precision.php –