私はミリ秒Datediff
の間GETDATE()
で取得しようとしています。SYSDATETIME()
SELECT DATEDIFF(ms, GETDATE() , SYSDATETIME());
私が得ている結果は0
or1
または2
or3
です。この違いの理由は何ですか?
私はミリ秒Datediff
の間GETDATE()
で取得しようとしています。SYSDATETIME()
SELECT DATEDIFF(ms, GETDATE() , SYSDATETIME());
私が得ている結果は0
or1
または2
or3
です。この違いの理由は何ですか?
これらは、2つの異なる時間を返すことができる2つの異なる関数呼び出しです。
さらに、精度が3〜4ミリ秒しかないデータ型をGETDATE
返しますが、データ型を返します。datetime
SYSDATETIME()
datetime2(7)
両方の呼び出しがまったく同時に返される場合でも、丸めが原因で発生している問題が発生する可能性があります。
DECLARE @D1 DATETIME2 = '2012-08-18 10:08:40.0650000'
DECLARE @D2 DATETIME = @D1 /*Rounded to 2012-08-18 10:08:40.067*/
SELECT DATEDIFF(ms, @D1 , @D2) /*Returns 2*/
GETDATE()
以下からわかるように、関数を代入すると1回だけ呼び出されるという、もう1つの答えは正しくありません。
WHILE DATEDIFF(ms, GETDATE() , GETDATE()) = 0
PRINT 'This will not run in an infinite loop'
Windows XPデスクトップでループを実行すると、GETDATE()
他SYSDATETIME
の何かが起こっている可能性があることを示す結果も表示されます。おそらく別のAPIを呼び出します。
CREATE TABLE #DT2
(
[D1] [DATETIME2](7),
[D2] [DATETIME2](7)
)
GO
INSERT INTO #DT2
VALUES(Getdate(), Sysdatetime())
GO 100
SELECT DISTINCT [D1],
[D2],
Datediff(MS, [D1], [D2]) AS MS
FROM #DT2
DROP TABLE #DT2
以下の結果の例
+-----------------------------+-----------------------------+-----+
| D1 | D2 | MS |
+-----------------------------+-----------------------------+-----+
| 2012-08-18 10:16:03.2500000 | 2012-08-18 10:16:03.2501680 | 0 |
| 2012-08-18 10:16:03.2530000 | 2012-08-18 10:16:03.2501680 | -3 |
| 2012-08-18 10:16:03.2570000 | 2012-08-18 10:16:03.2501680 | -7 |
| 2012-08-18 10:16:03.2600000 | 2012-08-18 10:16:03.2501680 | -10 |
| 2012-08-18 10:16:03.2630000 | 2012-08-18 10:16:03.2501680 | -13 |
| 2012-08-18 10:16:03.2630000 | 2012-08-18 10:16:03.2657914 | 2 |
| 2012-08-18 10:16:03.2670000 | 2012-08-18 10:16:03.2657914 | -2 |
| 2012-08-18 10:16:03.2700000 | 2012-08-18 10:16:03.2657914 | -5 |
| 2012-08-18 10:16:03.2730000 | 2012-08-18 10:16:03.2657914 | -8 |
| 2012-08-18 10:16:03.2770000 | 2012-08-18 10:16:03.2657914 | -12 |
| 2012-08-18 10:16:03.2800000 | 2012-08-18 10:16:03.2814148 | 1 |
+-----------------------------+-----------------------------+-----+
関心のある行は
| 2012-08-18 10:16:03.2600000 | 2012-08-18 10:16:03.2501680 | -10 |
| 2012-08-18 10:16:03.2630000 | 2012-08-18 10:16:03.2501680 | -13 |
この不一致は大きすぎて丸めの問題にはなりません。問題はレポートする複数の行に存在するため、2つの関数の呼び出しの間に遅延があるだけのタイミングの問題ではありませんGETDATE
が10:16:03.26X
、SYSDATETIME
10:16:03.250
2つの関数を同時に(まったく同時に)呼び出すことはできないため、これらは異なります。実行中の他のプロセスがタイミングに影響を与える可能性があります。量を変えることによってそれらが異なる可能性がある理由は数十あります。
代わりに2回の呼び出しで同じことを行った場合GetDate()
、データベースエンジンはそれらが同じものであると判断して結果を再利用できるほど賢いため、違いはありません。GetDate()
ただし、との使用SysDateTime()
は異なります。これは、それらが同じコードパスではないためです(異なることを行います)。
このように考えてください。とを見る1 + 2
と1 + 2
、最初の式と2番目の式が同じであることが簡単にわかります。したがって、計算を1回行うだけで済みます。とに変更する1 + Rand()
と1 + Rand()
、2つの異なる呼び出しが何を返すかを知る方法がないRand()
ため、別々に計算を行う必要があります。
この違いは、PRECISIONとRESOLUTIONの違いの良い例です(ここでは、精度を片側に残しておきましょう)。GETDATE()は、(明らかに)PRECISIONをミリ秒単位で含むDATETIMEを返しますが、タイトループに入れると、次に返される別の値が数ミリ秒後になります。RESOLUTIONは約3または4ミリ秒しかないため、毎秒約300の異なる値しか返すことができません。これについて詳しくは、こちらをご覧ください。これは、DATETIMEデータ型の設計機能/妥協点です。