Dalam SQL Server 2008 datatype tanggal telah ditambahkan.
Casting datetime
kolom date
adalah sargable dan dapat menggunakan indeks pada datetime
kolom.
select *
from T
where cast(DateTimeCol as date) = '20130101';
Opsi lain yang Anda miliki adalah menggunakan rentang.
select *
from T
where DateTimeCol >= '20130101' and
DateTimeCol < '20130102'
Apakah pertanyaan ini sama baiknya atau haruskah satu lebih disukai daripada yang lain?
sql-server
Mikael Eriksson
sumber
sumber
where cast(date_column as date) = 'value'
ketika disajikan dengan C # mirip denganwhere obj.date_column.Date == date_variable
.Jawaban:
Mekanisme di balik sargability casting hingga saat ini disebut pencarian dinamis .
SQL Server memanggil fungsi internal
GetRangeThroughConvert
untuk mendapatkan awal dan akhir kisaran.Agak mengherankan ini tidak kisaran yang sama dengan nilai literal Anda.
Membuat tabel dengan baris per halaman dan 1440 baris per hari
Lalu berlari
Kueri pertama telah
1443
membaca dan yang kedua2883
sehingga membaca seluruh hari tambahan kemudian membuangnya terhadap predikat residual.Rencana tersebut menunjukkan predikat pencarian tersebut
Jadi alih-alih
>= '20130101' ... < '20130102'
membacanya,> '20121231' ... < '20130102'
buang semua2012-12-31
baris.Kerugian lain dari mengandalkannya adalah bahwa perkiraan kardinalitas mungkin tidak seakurat dengan kueri rentang tradisional. Ini dapat dilihat dalam versi amandemen SQL Fiddle Anda .
Semua 100 baris dalam tabel sekarang cocok dengan predikat (dengan datetimes terpisah 1 menit pada hari yang sama).
Kueri (rentang) kedua dengan benar memperkirakan bahwa 100 akan cocok dan menggunakan pemindaian indeks berkerumun. The
CAST( AS DATE)
permintaan salah memperkirakan bahwa hanya satu baris akan cocok dan menghasilkan rencana dengan pencarian kunci.Statistik tidak diabaikan sepenuhnya. Jika semua baris dalam tabel memiliki yang sama
datetime
dan cocok dengan predikat (misalnya20130101 00:00:00
atau20130101 01:00:00
) maka rencana menunjukkan pemindaian indeks berkerumun dengan perkiraan 31,6228 baris.Jadi dalam hal ini tampaknya perkiraan tersebut berasal dari rumus di sini .
Jika semua baris dalam tabel memiliki yang sama
datetime
dan tidak cocok dengan predikat (mis.20130102 01:00:00
) Maka jatuh kembali ke perkiraan jumlah baris 1 dan rencana dengan pencarian.Untuk kasus di mana tabel memiliki lebih dari satu
DISTINCT
nilai, baris yang diestimasi tampaknya sama seperti jika kueri mencari dengan tepat20130101 00:00:00
.Jika histogram statistik memiliki langkah pada
2013-01-01 00:00:00.000
maka estimasi akan didasarkan padaEQ_ROWS
(yaitu tidak memperhitungkan waktu lain pada tanggal itu). Kalau tidak, jika tidak ada langkah sepertinya menggunakanAVG_RANGE_ROWS
dari langkah-langkah sekitarnya.Karena
datetime
memiliki presisi sekitar 3ms dalam banyak sistem akan ada sangat sedikit nilai duplikat aktual dan angka ini akan menjadi 1.sumber
TL;DR
bagian dengan beberapa poin dengan kasus yang berbeda menambahkan apakah dalam kasus itu, para pemain sampai saat ini apakah itu ide yang baik atau tidak?Saya tahu bahwa ini memiliki Great Answer® lama dari Martin, tapi saya ingin menambahkan beberapa perubahan pada perilaku di sini dalam versi SQL Server yang lebih baru. Ini tampaknya hanya telah diuji hingga 2008R2.
Dengan PETUNJUK PENGGUNAAN baru yang memungkinkan dilakukannya beberapa perkiraan waktu perjalanan kardinalitas, kita dapat melihat ketika segala sesuatu berubah.
Menggunakan pengaturan yang sama seperti pada SQL Fiddle.
Kami dapat menguji level yang berbeda seperti:
Rencana untuk semua ini tersedia di sini . Level Compat 100 dan 110 keduanya memberikan rencana pencarian kunci, tetapi mulai dengan level compat 120, kita mulai mendapatkan rencana pemindaian yang sama dengan estimasi 100 baris. Ini berlaku hingga level 140.
Estimasi kardinalitas untuk
>= '20130101', < '20130102'
rencana tetap di 100, yang diharapkan.sumber