Gambar © Mark Boyle | Dewan Hari Australia NSW.
Gambar milik artis masing-masing. Semua hak dilindungi undang-undang.
AT TIME ZONE adalah fitur yang sangat keren dan saya baru menyadarinya belakangan ini, meskipun Microsoft telah memiliki halaman tentangnya sejak Desember.
Saya tinggal di Adelaide di Australia. Dan seperti lebih dari satu miliar orang lain di dunia, orang Adelaide harus menghadapi zona waktu setengah jam. Di musim dingin, kami UTC+9:30, dan di musim panas kami UTC+10:30. Kecuali jika Anda membaca ini di belahan bumi utara, Anda harus ingat bahwa dengan 'musim dingin', maksud saya April hingga Oktober. Waktu musim panas adalah Oktober hingga April, dan Sinterklas duduk di pantai dengan minuman dingin, berkeringat melalui jas dan janggut merahnya yang tebal. Kecuali dia menyelamatkan nyawa, tentu saja.
Di Australia, kami memiliki tiga zona waktu utama (Barat, Tengah, dan Timur), tetapi ini meluas hingga lima di musim panas, karena tiga negara bagian yang membentang ke ujung utara Australia (WA, Qld, dan NT) tidak mencoba untuk menyimpan siang hari. Mereka cukup dekat dengan khatulistiwa untuk tidak peduli, atau semacamnya. Sangat menyenangkan bagi bandara Gold Coast, yang landasan pacunya melintasi perbatasan NSW-QLD.
Server basis data sering berjalan di UTC, karena lebih mudah untuk tidak berurusan dengan konversi antara UTC dan lokal (dan sebaliknya) di SQL Server. Bertahun-tahun yang lalu saya ingat harus memperbaiki laporan yang mencantumkan insiden yang terjadi bersama dengan waktu respons (saya telah membuat blog tentang ini sejak). Mengukur SLA cukup mudah – saya dapat melihat bahwa satu insiden terjadi selama jam kerja pelanggan, dan mereka merespons dalam satu jam. Saya dapat melihat bahwa insiden lain terjadi di luar jam kerja, dan responsnya dalam waktu dua jam. Masalah muncul ketika laporan dibuat pada akhir periode ketika zona waktu berubah, menyebabkan insiden yang sebenarnya terjadi pada 17:30 (di luar jam) dicatat seolah-olah terjadi pada 16:30 (dalam jam) . Tanggapannya memakan waktu sekitar 90 menit, tidak apa-apa, tetapi laporan menunjukkan sebaliknya.
Semua ini diperbaiki di SQL Server 2016.
Cara menggunakan AT TIME ZONE di SQL Server 2016
Sekarang, dengan AT TIME ZONE, alih-alih mengatakan:'20160101 00:00 +10:30', saya bisa mulai dengan nilai datetime yang tidak memiliki offset zona waktu, dan menggunakan AT TIME ZONE untuk menjelaskan bahwa itu ada di Adelaide.
SELECT CONVERT(datetime,'20160101 00:00') PADA ZONA WAKTU 'Cen. Waktu Standar Australia'; -- 01-01-2016 00:00:00.000 +10:30
Dan ini dapat dikonversi ke waktu Amerika dengan menambahkan AT TIME ZONE lagi.
SELECT CONVERT(datetime,'20160101 00:00') PADA ZONA WAKTU 'Cen. Waktu Standar Australia' AT TIME ZONE 'Waktu Standar Timur AS'; -- 31-12-2015 08:30:00.000 -05:00
Sekarang, saya tahu ini jauh lebih bertele-tele. Dan saya perlu secara eksplisit mengonversi string ke datetime, untuk menghindari kesalahan yang mengatakan:
Tipe data argumen varchar tidak valid untuk argumen 1 dari fungsi AT TIME ZONE.Tapi terlepas dari itu bertele-tele, saya menyukainya, karena saya tidak perlu mengetahui bahwa Adelaide berada di +10:30, atau bahwa Timur adalah -5:00 – saya hanya perlu mengetahui zona waktu dengan nama. Mencari tahu apakah waktu musim panas harus diterapkan atau tidak ditangani untuk saya, dan saya tidak perlu melakukan konversi apa pun dari lokal ke UTC untuk menetapkan beberapa garis dasar.
Ini bekerja dengan menggunakan registri Windows, yang memiliki semua informasi di dalamnya, tetapi sayangnya, itu tidak sempurna ketika melihat ke masa lalu. Australia mengubah tanggal pada tahun 2008, dan AS mengubah tanggalnya pada tahun 2005 – kedua negara menghemat waktu siang hari untuk lebih banyak tahun. AT TIME ZONE memahami hal ini. Tetapi tampaknya tidak menghargai bahwa di Australia pada tahun 2000, berkat Olimpiade Sydney, Australia memulai musim panas sekitar dua bulan sebelumnya. Ini sedikit membuat frustrasi, tetapi ini bukan kesalahan SQL – kita harus menyalahkan Windows untuk itu. Saya kira registri Windows tidak mengingat perbaikan terbaru yang terjadi sekitar tahun itu. (Catatan untuk diri sendiri:Saya mungkin perlu meminta seseorang di tim Windows untuk memperbaikinya…)
Kegunaannya terus berlanjut!
Nama zona waktu itu bahkan tidak perlu konstan. Saya dapat memasukkan variabel, dan bahkan menggunakan kolom:
DENGAN PeopleAndTZs AS( SELECT * FROM (VALUES ('Rob', 'Cen. Australia Standard Time'), ('Paul', 'New Zealand Standard Time'), ('Aaron', 'US Eastern Standard Time' ) ) t (orang, tz))PILIH tz.person, SYSDATETIMEOFFSET() PADA ZONA WAKTU tz.tz DARI PeopleAndTZs tz; /* Rob 18-07-2016 18:29:11.9749952 +09:30 Paul 18-07-2016 20:59:11.9749952 +12:00 Aaron 18-07-2016 04:59:11.9749952 -04:00*/(Karena saya melakukannya sebelum 18:30 di sini di Adelaide, yang kebetulan hampir jam 9 malam di Selandia Baru tempat Paul berada, dan hampir jam 5 pagi ini di bagian timur Amerika tempat Aaron berada.)
Ini akan membuat saya dengan mudah melihat jam berapa sekarang bagi orang-orang di mana pun mereka berada di dunia, dan untuk melihat siapa yang terbaik untuk menanggapi beberapa masalah, tanpa harus melakukan konversi waktu-tanggal manual. Dan terlebih lagi, itu akan membuat saya melakukannya untuk orang-orang di masa lalu. Saya dapat memiliki laporan yang menganalisis zona waktu mana yang memungkinkan jumlah peristiwa paling banyak terjadi selama jam kerja.
Zona waktu tersebut tercantum di
sys.time_zone_info
, bersama dengan offset saat ini, dan apakah daylight saving saat ini diterapkan.nama current_utc_offset is_saat ini_dst Waktu Standar Singapura +08:00 0 W. Waktu Standar Australia +08:00 0 Waktu Standar Taipei +08:00 0 Waktu Standar Ulaanbaatar +09:00 1 Waktu Standar Korea Utara +08:30 0 Waktu Standar Australia Tengah W. +08:45 0 Waktu Standar Transbaikal +09:00 0 Waktu Standar Tokyo +09:00 0 Pengambilan sampel baris dari sys.time_zone_info
Saya hanya benar-benar tertarik pada apa namanya, tetapi bagaimanapun juga. Dan menarik untuk melihat bahwa ada zona waktu yang disebut "Aus Central W. Standard Time" yang berada di seperempat jam. pergilah. Juga perlu diperhatikan bahwa tempat-tempat dirujuk menggunakan nama Waktu Standar mereka, bahkan jika mereka sedang mengamati DST. Seperti Ulaanbaatar dalam daftar di atas, yang tidak terdaftar sebagai Ulaanbaatar Daylight Time. Hal ini dapat membuat orang mengulang ketika mereka mulai menggunakan AT TIME ZONE.
Dapatkah AT TIME ZONE menyebabkan masalah kinerja?
Sekarang, saya yakin Anda bertanya-tanya apa dampak penggunaan AT TIME ZONE terhadap pengindeksan.
Dari segi bentuk plan, tidak ada bedanya dengan menangani datetimeoffset pada umumnya. Jika saya memiliki nilai datetime, seperti di kolom AdventureWorks Sales.SalesOrderHeader.OrderDate (di mana saya membuat indeks bernama rf_IXOD), maka jalankan kedua kueri ini:
pilih OrderDate, SalesOrderID dari Sales.SalesOrderHeader di mana OrderDate>=convert(datetime,'20110601 00:00') pada zona waktu 'US Eastern Standard Time' dan OrderDateDan pertanyaan ini:
pilih OrderDate, SalesOrderID dari Sales.SalesOrderHeader di mana OrderDate>=convert(datetimeoffset,'20110601 00:00 -04:00') dan OrderDateDalam kedua kasus tersebut, Anda mendapatkan paket yang terlihat seperti ini:
Tapi jika kita telusuri lebih dekat, ada masalah.
Yang menggunakan AT TIME ZONE tidak menggunakan statistik dengan baik. Ia berpikir akan melihat 5.170 baris keluar dari Pencarian Indeks itu, padahal sebenarnya hanya ada 217. Mengapa 5.170? Nah, postingan terbaru Aaron, “Memperhatikan Estimasi,” menjelaskannya, dengan merujuk pada postingan “Estimasi Kardinalitas untuk Beberapa Predikat” dari Paul. 5.170 adalah 31.465 (baris dalam tabel) * 0,3 * sqrt(0,3).
Kueri kedua benar, memperkirakan 217. Tidak ada fungsi yang terlibat, Anda tahu.
Ini mungkin cukup adil. Maksud saya – ketika membuat rencana, itu tidak akan meminta registri untuk informasi yang dibutuhkannya, jadi itu benar-benar tidak tahu berapa banyak yang harus diperkirakan. Tapi ada potensi untuk menjadi masalah.
Jika saya menambahkan predikat tambahan yang saya tahu tidak akan menjadi masalah, maka perkiraan saya sebenarnya turun lebih jauh – hingga 89,9 baris.
pilih OrderDate, SalesOrderID dari Sales.SalesOrderHeader di mana OrderDate>=convert(datetime,'20110601 00:00') pada zona waktu 'US Eastern Standard Time' dan OrderDate=convert(datetimeoffset,'20110601 00:00 +14:00') dan OrderDate Memperkirakan terlalu banyak baris berarti terlalu banyak memori yang dialokasikan, tetapi memperkirakan terlalu sedikit dapat menyebabkan terlalu sedikit memori, yang berpotensi membutuhkan tumpahan untuk memperbaiki masalah (yang seringkali dapat menjadi bencana dari perspektif kinerja). Baca postingan Aaron untuk informasi lebih lanjut tentang bagaimana perkiraan yang buruk bisa menjadi buruk.
Ketika saya mempertimbangkan bagaimana menangani menampilkan nilai untuk orang-orang itu dari sebelumnya, saya dapat menggunakan kueri seperti ini:
DENGAN PeopleAndTZs AS( SELECT * FROM (VALUES ('Rob', 'Cen. Australia Standard Time'), ('Paul', 'New Zealand Standard Time'), ('Aaron', 'US Eastern Standard Time' ) ) t (person, tz))PILIH tz.person, o.SalesOrderID, o.OrderDate PADA TIME ZONE 'UTC' AT TIME ZONE tz.tzFROM PeopleAndTZs tzCROSS GABUNG Penjualan.SalesOrderHeader oWHERE o.SalesOrderID BETWEEN; 44001 DAN 44010 pra>Dan dapatkan paket ini:
…yang tidak memiliki masalah seperti itu – Compute Scalar paling kanan mengubah tanggal OrderDate menjadi datetimeoffset untuk UTC, dan Compute Scalar paling kiri mengubahnya menjadi zona waktu yang sesuai untuk orang tersebut. Peringatannya adalah karena saya melakukan CROSS JOIN, dan itu sepenuhnya disengaja.
Keuntungan dan Kerugian dari metode konversi waktu lainnya
Sebelum AT TIME ZONE, salah satu fitur favorit saya, tetapi sering tidak dihargai, SQL 2008 adalah tipe data datetimeoffset. Ini memungkinkan data tanggal/waktu disimpan dengan zona waktu juga, seperti '20160101 00:00 +10:30', yaitu saat kami merayakan Tahun Baru di Adelaide tahun ini. Untuk melihat saat itu di US Eastern, saya dapat menggunakan fungsi SWITCHOFFSET.
SELECT SWITCHOFFSET('20160101 00:00 +10:30', '-05:00'); -- 31-12-2015 08:30:00.0000000 -05:00Ini adalah momen yang sama dalam waktu, tetapi di bagian dunia yang berbeda. Jika saya sedang menelepon seseorang di North Carolina atau New York, mengucapkan Selamat Tahun Baru karena baru lewat tengah malam di Adelaide, mereka akan berkata, “Apa maksudmu? Ini masih waktu sarapan di sini pada Malam Tahun Baru!”
Masalahnya adalah untuk melakukan ini, saya perlu tahu bahwa pada bulan Januari, Adelaide adalah +10:30 dan US Eastern adalah –5:00. Dan itu sering menyakitkan. Terutama jika saya bertanya tentang akhir Maret, awal April, Oktober, awal November – saat-saat dalam setahun ketika orang tidak dapat memastikan zona waktu mana orang-orang di negara lain berada karena mereka berubah satu jam untuk musim panas, dan mereka semua melakukannya menurut aturan yang berbeda. Komputer saya memberi tahu saya di zona waktu apa orang-orang berada sekarang, tetapi jauh lebih sulit untuk mengatakan di zona waktu apa mereka akan berada di waktu lain dalam setahun.
Untuk beberapa informasi lain tentang mengonversi antar zona waktu, dan bagaimana orang-orang seperti Aaron menangani waktu musim panas, lihat tautan berikut:
- Menggunakan AT TIME ZONE untuk memperbaiki laporan lama (itu saya!)
- Menangani konversi antar zona waktu di SQL Server – bagian 1
- Menangani konversi antar zona waktu di SQL Server – bagian 2
- Menangani konversi antar zona waktu di SQL Server – bagian 3
Dan beberapa dokumentasi resmi Microsoft:
- PADA ZONA WAKTU (Transact-SQL)
- sys.time_zone_info (Transact-SQL)
- Bantuan dan dukungan waktu musim panas
Haruskah Anda menggunakan AT TIME ZONE?
AT TIME ZONE tidak sempurna. Tapi itu benar-benar berguna – sangat luar biasa. Cukup fleksibel untuk menerima kolom dan variabel sebagai input, dan saya dapat melihat potensi yang sangat besar untuk itu. Tetapi jika itu akan menyebabkan perkiraan saya keluar, maka saya harus berhati-hati. Untuk tujuan tampilan, ini seharusnya tidak masalah sama sekali, dan di situlah saya dapat melihatnya paling berguna. Mempermudah untuk mengonversi nilai tampilan ke atau dari UTC (atau ke atau dari waktu lokal), tanpa ada yang harus memecahkan otak mereka tentang offset dan DST, adalah kemenangan besar.
Ini benar-benar salah satu fitur favorit saya dari SQL Server 2016. Saya sudah lama menginginkan hal seperti ini.
Oh, dan sebagian besar dari miliaran orang di zona waktu setengah jam itu ada di India. Tapi Anda mungkin sudah tahu bahwa…