Bild © Mark Junge | Australia Day Council of NSW.
Bilder Eigentum der jeweiligen Künstler. Alle Rechte vorbehalten.
AT TIME ZONE ist so ein cooles Feature und ich hatte es bis vor kurzem nicht bemerkt, obwohl Microsoft seit Dezember eine Seite darüber hat.
Ich lebe in Adelaide in Australien. Und wie über eine Milliarde andere Menschen auf der Welt müssen die Einwohner von Adelaide mit einer Zeitzone von einer halben Stunde fertig werden. Im Winter ist es UTC+9:30 und im Sommer UTC+10:30. Nur wenn Sie dies auf der Nordhalbkugel lesen, müssen Sie sich daran erinnern, dass ich mit „Winter“ April bis Oktober meine. Sommerzeit ist von Oktober bis April, und der Weihnachtsmann sitzt mit einem kalten Getränk am Strand und schwitzt durch seinen dicken roten Anzug und seinen Bart. Es sei denn natürlich, er rettet Leben.
Innerhalb Australiens haben wir drei Hauptzeitzonen (Western, Central und Eastern), aber diese erstrecken sich im Sommer auf fünf, während die drei Bundesstaaten, die sich bis zum nördlichen Ende Australiens erstrecken (WA, Qld und NT), dies nicht tun Versuchen Sie, das Tageslicht zu retten. Sie sind nah genug am Äquator, um sich nicht darum zu kümmern, oder so etwas. Für den Flughafen Gold Coast, dessen Start- und Landebahn die Grenze zwischen NSW und QLD überquert, ist das ein Riesenspaß.
Datenbankserver laufen oft in UTC, weil es einfach einfacher ist, sich nicht mit der Konvertierung zwischen UTC und lokal (und umgekehrt) in SQL Server herumschlagen zu müssen. Ich erinnere mich, dass ich vor vielen Jahren einen Bericht korrigieren musste, der aufgetretene Vorfälle zusammen mit den Reaktionszeiten auflistete (seitdem habe ich darüber gebloggt). Das Messen von SLA war recht einfach – ich konnte sehen, dass ein Vorfall während der Arbeitszeit des Kunden passierte und dass er innerhalb einer Stunde reagierte. Ich konnte sehen, dass sich ein weiterer Vorfall außerhalb der Arbeitszeit ereignete, und die Reaktion erfolgte innerhalb von zwei Stunden. Das Problem trat auf, als am Ende eines Zeitraums, in dem sich die Zeitzone änderte, ein Bericht erstellt wurde, wodurch ein Vorfall, der tatsächlich um 17:30 Uhr (außerhalb der Geschäftszeiten) passierte, so aufgeführt wurde, als ob er um 16:30 Uhr (innerhalb der Geschäftszeiten) aufgetreten wäre. . Die Antwort hatte ungefähr 90 Minuten gedauert, was in Ordnung war, aber der Bericht zeigte etwas anderes.
All dies wurde in SQL Server 2016 behoben.
Verwendung von AT TIME ZONE in SQL Server 2016
Jetzt kann ich mit AT TIME ZONE, anstatt zu sagen:'20160101 00:00 +10:30', mit einem datetime-Wert beginnen, der keinen Zeitzonenoffset hat, und AT TIME ZONE verwenden, um zu erklären, dass er in Adelaide liegt.
SELECT CONVERT(datetime,'20160101 00:00') AT TIME ZONE 'Cen. Australische Standardzeit'; -- 01.01.2016 00:00:00.000 +10:30
Und diese kann durch erneutes Anhängen von AT TIME ZONE in die amerikanische Zeit umgerechnet werden.
SELECT CONVERT(datetime,'20160101 00:00') AT TIME ZONE 'Cen. Australische Standardzeit“ AT TIME ZONE „US Eastern Standard Time“; -- 2015-12-31 08:30:00.000 -05:00
Nun, ich weiß, das ist viel langwieriger. Und ich muss die Zeichenfolge explizit in datetime konvertieren, um einen Fehler zu vermeiden, der besagt:
Der Argumentdatentyp varchar ist für Argument 1 der Funktion AT TIME ZONE ungültig.Aber trotz der Langatmigkeit liebe ich es, denn zu keinem Zeitpunkt musste ich herausfinden, dass Adelaide +10:30 oder Eastern -5:00 war – ich musste einfach die Zeitzone beim Namen kennen. Herauszufinden, ob die Sommerzeit gelten sollte oder nicht, wurde für mich erledigt, und ich musste keine Konvertierung von lokal nach UTC vornehmen, um eine Basislinie festzulegen.
Es funktioniert, indem es die Windows-Registrierung verwendet, die all diese Informationen enthält, aber leider ist es nicht perfekt, wenn man in die Vergangenheit blickt. Australien änderte die Daten 2008, und die USA änderten ihre Daten 2005 – beide Länder sparten das Tageslicht für einen Großteil des Jahres. AT TIME ZONE versteht das. Aber es scheint nicht zu würdigen, dass Australien im Jahr 2000 dank der Olympischen Spiele in Sydney etwa zwei Monate früher mit der Sommerzeit begonnen hat. Das ist ein wenig frustrierend, aber es ist nicht die Schuld von SQL – wir müssen Windows dafür verantwortlich machen. Ich denke, die Windows-Registrierung erinnert sich nicht an den Hotfix, der in diesem Jahr lief. (Notiz an mich selbst:Ich muss vielleicht jemanden im Windows-Team bitten, das zu beheben …)
Die Nützlichkeit geht jedoch weiter!
Dieser Zeitzonenname muss nicht einmal eine Konstante sein. Ich kann Variablen übergeben und sogar Spalten verwenden:
WITH PeopleAndTZs AS( SELECT * FROM (VALUES ('Rob', 'Cen. Australia Standard Time'), ('Paul', 'New Zealand Standard Time'), ('Aaron', 'US Eastern Standard Time' ) ) t (Person, tz))SELECT tz.person, SYSDATETIMEOFFSET() AT TIME ZONE tz.tz FROM PeopleAndTZs tz; /* Rob 2016-07-18 18:29:11.9749952 +09:30 Paul 2016-07-18 20:59:11.9749952 +12:00 Aaron 2016-07-18 04:59:11.9749952 -04:00*/
(Weil ich das hier in Adelaide kurz vor 18:30 Uhr ausgeführt habe, was in Neuseeland, wo Paul ist, fast 21:00 Uhr ist, und heute Morgen im östlichen Teil von Amerika, wo Aaron ist, fast 5:00 Uhr morgens.)
Auf diese Weise könnte ich leicht sehen, wie spät es für Menschen ist, wo immer sie sich auf der Welt befinden, und sehen, wer am besten auf ein Problem reagieren könnte, ohne manuelle Datums- und Uhrzeitkonvertierungen durchführen zu müssen. Und noch mehr, es ließ mich es für Menschen in der Vergangenheit tun. Ich könnte einen Bericht haben, der analysiert, in welchen Zeitzonen die meisten Ereignisse während der Geschäftszeiten auftreten würden.
Diese Zeitzonen sind in sys.time_zone_info
aufgelistet , zusammen mit dem aktuellen Offset und ob derzeit Sommerzeit gilt.
Name | current_utc_offset | is_currently_dst |
---|---|---|
Singapur-Standardzeit | +08:00 | 0 |
W. Australische Standardzeit | +08:00 | 0 |
Taipeh-Normalzeit | +08:00 | 0 |
Ulaanbaatar-Standardzeit | +09:00 | 1 |
Nordkoreanische Normalzeit | +08:30 | 0 |
Aus Central W. Standard Time | +08:45 | 0 |
Transbaikalische Normalzeit | +09:00 | 0 |
Tokio Normalzeit | +09:00 | 0 |
Sampling von Zeilen aus sys.time_zone_info
Mich interessiert eigentlich nur der Name, aber egal. Und es ist interessant zu sehen, dass es eine Zeitzone namens „Aus Central W. Standard Time“ gibt, die auf der Viertelstunde liegt. Stelle dir das vor. Erwähnenswert ist auch, dass Orte mit ihrem Standardzeitnamen bezeichnet werden, auch wenn sie derzeit Sommerzeit haben. Wie Ulaanbaatar in dieser Liste oben, das nicht als Ulaanbaatar Daylight Time aufgeführt ist. Dies kann Leute aus der Fassung bringen, wenn sie anfangen, AT TIME ZONE zu verwenden.
Kann AT TIME ZONE Leistungsprobleme verursachen?
Jetzt fragen Sie sich sicher, welche Auswirkungen die Verwendung von AT TIME ZONE auf die Indizierung haben könnte.
In Bezug auf die Form des Plans unterscheidet es sich nicht vom Umgang mit datetimeoffset im Allgemeinen. Wenn ich datetime-Werte habe, wie z. B. in der AdventureWorks-Spalte Sales.SalesOrderHeader.OrderDate (auf deren Grundlage ich einen Index namens rf_IXOD erstellt habe), dann führen Sie diese beiden Abfragen aus:
wählen Sie OrderDate, SalesOrderID aus Sales.SalesOrderHeader aus, wobei OrderDate>=convert(datetime,'20110601 00:00') in der Zeitzone 'US Eastern Standard Time' und OrderDateUnd diese Abfrage:
orderDate, SalesOrderID aus Sales.SalesOrderHeader auswählen, wobei OrderDate>=convert(datetimeoffset,'20110601 00:00 -04:00') und OrderDateIn beiden Fällen erhalten Sie Pläne, die wie folgt aussehen:
Aber wenn wir etwas genauer nachforschen, gibt es ein Problem.
Derjenige, der AT TIME ZONE verwendet, verwendet die Statistiken nicht sehr gut. Es geht davon aus, dass 5.170 Zeilen aus dieser Indexsuche herauskommen werden, obwohl es tatsächlich nur 217 gibt. Warum 5.170? Nun, Aarons kürzlich erschienener Beitrag „Auf Schätzungen achten“ erklärt es, indem er sich auf den Beitrag „Kardinalitätsschätzung für mehrere Prädikate“ von Paul bezieht. 5.170 ist 31.465 (Zeilen in der Tabelle) * 0,3 * sqrt(0,3).
Die zweite Abfrage macht es richtig und schätzt 217. Keine Funktionen beteiligt, sehen Sie.
Das ist wahrscheinlich fair genug. Ich meine – zu dem Zeitpunkt, an dem der Plan erstellt wird, hat es das Register nicht nach den benötigten Informationen gefragt, also weiß es wirklich nicht, wie viele es schätzen soll. Aber es besteht die Möglichkeit, dass dies ein Problem darstellt.
Wenn ich zusätzliche Prädikate hinzufüge, von denen ich weiß, dass sie kein Problem darstellen können, sinken meine Schätzungen sogar noch weiter – bis auf 89,9 Zeilen.
wählen Sie OrderDate, SalesOrderID aus Sales.SalesOrderHeader aus, wobei OrderDate>=convert(datetime,'20110601 00:00') in der Zeitzone 'US Eastern Standard Time' und OrderDate=convert(datetimeoffset,'20110601 00:00 +14:00') und OrderDate Das Schätzen zu vieler Zeilen bedeutet, dass zu viel Arbeitsspeicher zugewiesen wird, aber das Schätzen zu weniger kann zu wenig Arbeitsspeicher führen, sodass möglicherweise ein Überlauf erforderlich ist, um das Problem zu beheben (was aus Leistungssicht oft katastrophal sein kann). Lesen Sie Aarons Beitrag, um mehr darüber zu erfahren, wie schlecht Schätzungen sein können.
Wenn ich darüber nachdenke, wie ich mit der Anzeige von Werten für diese Personen von früher umgehen soll, kann ich Abfragen wie diese verwenden:
WITH PeopleAndTZs AS( SELECT * FROM (VALUES ('Rob', 'Cen. Australia Standard Time'), ('Paul', 'New Zealand Standard Time'), ('Aaron', 'US Eastern Standard Time' ) ) t (person, tz))SELECT tz.person, o.SalesOrderID, o.OrderDate AT TIME ZONE 'UTC' AT TIME ZONE tz.tzFROM PeopleAndTZs tzCROSS JOIN Sales.SalesOrderHeader oWHERE o.SalesOrderID BETWEEN 44001 AND 44010;Und holen Sie sich diesen Plan:
…das keine derartigen Bedenken hat – der Compute Scalar ganz rechts konvertiert das Datetime OrderDate in datetimeoffset für UTC, und der Compute Scalar ganz links konvertiert es in die entsprechende Zeitzone für die Person. Die Warnung ist, weil ich einen CROSS JOIN mache, und das war völlig beabsichtigt.
Vor- und Nachteile anderer Zeitumrechnungsmethoden
Vor AT TIME ZONE war eines meiner liebsten, aber oft verkannten Features von SQL 2008 der Datentyp datetimeoffset. Dadurch können auch Datums-/Uhrzeitdaten mit der Zeitzone gespeichert werden, z. B. „20160101 00:00 +10:30“, wenn wir dieses Jahr in Adelaide Neujahr gefeiert haben. Um zu sehen, wann das in US Eastern war, kann ich die Funktion SWITCHOFFSET verwenden.
SWITCHOFFSET('20160101 00:00 +10:30', '-05:00'); -- 2015-12-31 08:30:00.0000000 -05:00Dies ist der gleiche Zeitpunkt, aber in einem anderen Teil der Welt. Wenn ich mit jemandem in North Carolina oder New York telefonieren und ihm ein frohes neues Jahr wünschen würde, weil es in Adelaide kurz nach Mitternacht war, würde er sagen:„Was meinst du? An Silvester ist hier noch Frühstückszeit!“
Das Problem ist, dass ich dazu wissen muss, dass Adelaide im Januar +10:30 und US Eastern –5:00 ist. Und das tut oft weh. Vor allem, wenn ich nach Ende März, Anfang April, Oktober, Anfang November frage – jene Jahreszeiten, in denen die Menschen nicht sicher sein können, in welcher Zeitzone sich Menschen in anderen Ländern befanden, weil sie sich um eine Stunde auf Sommerzeit umstellen, und sie alle tun dies nach unterschiedlichen Regeln. Mein Computer sagt mir, in welcher Zeitzone sich die Leute jetzt befinden, aber es ist viel schwieriger zu sagen, in welcher Zeitzone sie sich zu anderen Jahreszeiten aufhalten werden.
Weitere Informationen zum Umrechnen zwischen Zeitzonen und dazu, wie Leute wie Aaron mit der Sommerzeit umgegangen sind, finden Sie unter den folgenden Links:
- Mit AT TIME ZONE einen alten Bericht reparieren (das bin ich!)
- Handhabung der Konvertierung zwischen Zeitzonen in SQL Server – Teil 1
- Handhabung der Konvertierung zwischen Zeitzonen in SQL Server – Teil 2
- Handhabung der Konvertierung zwischen Zeitzonen in SQL Server – Teil 3
Und einige offizielle Microsoft-Dokumentation:
- IN DER ZEITZONE (Transact-SQL)
- sys.time_zone_info (Transact-SQL)
- Hilfe und Support zur Sommerzeit
Sollten Sie AT TIME ZONE verwenden?
AT TIME ZONE ist nicht perfekt. Aber es ist wirklich nützlich – unglaublich. Es ist flexibel genug, um Spalten und Variablen als Eingabe zu akzeptieren, und ich sehe ein riesiges Potenzial dafür. Aber wenn es dazu führt, dass meine Schätzungen abweichen, muss ich vorsichtig sein. Für Anzeigezwecke sollte dies jedoch überhaupt keine Rolle spielen, und dort kann ich sehen, dass es am nützlichsten ist. Es ist ein großer Gewinn, einen Anzeigewert einfacher in oder von UTC (oder in oder von einer Ortszeit) umzuwandeln, ohne dass sich jemand den Kopf über Offsets und DST zerbrechen muss.
Das ist wirklich eines meiner Lieblingsfeatures von SQL Server 2016. Ich habe lange nach so etwas geschrien.
Oh, und die meisten dieser Milliarden Menschen in der Halbstunden-Zeitzone leben in Indien. Aber das wussten Sie wahrscheinlich schon…