Kami menggunakan SQL Server 2008 R2, dan memiliki tabel yang sangat besar (100M + baris) dengan indeks id primer, dan datetime
kolom dengan indeks tidak tercakup. Kami melihat beberapa perilaku klien / server yang sangat tidak biasa berdasarkan penggunaan order by
klausa khusus pada kolom datetime indeks .
Saya membaca posting berikut: /programming/1716798/sql-server-2008-ordering-by-datetime-is-too-slow tetapi ada lebih banyak hal yang terjadi dengan klien / server daripada apa yang ada mulai dijelaskan di sini.
Jika kami menjalankan kueri berikut (diedit untuk melindungi beberapa konten):
select *
from [big table]
where serial_number = [some number]
order by test_date desc
Permintaan habis waktu setiap waktu. Dalam SQL Server Profiler kueri yang dieksekusi terlihat seperti ini ke server:
exec sp_cursorprepexec @p1 output,@p2 output,NULL,N'select * .....
Sekarang jika Anda memodifikasi kueri, katakan ini:
declare @temp int;
select * from [big table]
where serial_number = [some number]
order by test_date desc
SQL Server Profiler memperlihatkan kueri yang dieksekusi seperti ini ke server, dan langsung berfungsi:
exec sp_prepexec @p1 output, NULL, N'declare @temp int;select * from .....
Faktanya, Anda bahkan dapat memberikan komentar kosong ('-;') daripada pernyataan pernyataan yang tidak digunakan dan mendapatkan hasil yang sama. Jadi awalnya kami menunjuk ke sp pra-prosesor sebagai akar penyebab masalah ini, tetapi jika Anda melakukan ini:
select *
from [big table]
where serial_number = [some number]
order by Cast(test_date as smalldatetime) desc
Ini juga bekerja secara instan (Anda dapat menampilkannya sebagai datetime
tipe lain ), mengembalikan hasilnya dalam milidetik. Dan profiler menunjukkan permintaan ke server sebagai:
exec sp_cursorprepexec @p1 output, @p2 output, NULL, N'select * from .....
Sehingga agak mengecualikan sp_cursorprepexec
prosedur dari penyebab penuh masalah. Tambahkan ke fakta bahwa sp_cursorprepexec
ini juga disebut ketika tidak ada 'pesanan oleh' digunakan dan hasilnya juga dikembalikan secara instan.
Kami telah sedikit menelusuri Google untuk masalah ini, dan saya melihat masalah serupa diposting dari orang lain, tetapi tidak ada yang memecahnya ke tingkat ini.
Jadi, sudahkah orang lain menyaksikan perilaku ini? Adakah yang punya solusi lebih baik daripada meletakkan SQL yang tidak berarti di depan pernyataan pilih untuk mengubah perilaku? Karena SQL Server harus menjalankan perintah setelah data dikumpulkan, sepertinya ini adalah bug di server yang telah bertahan lama. Kami telah menemukan perilaku ini konsisten di banyak tabel besar kami, dan dapat direproduksi.
Suntingan:
Saya juga harus menambahkan memasukkan forceseek
juga membuat masalah hilang.
Saya harus menambahkan untuk membantu para pencari, kesalahan batas waktu ODBC dilemparkan adalah: [Microsoft] [ODBC SQL Server Driver] Operasi dibatalkan
Ditambahkan 10/12/2012: Masih memburu akar penyebab, (bersama dengan membangun sampel untuk diberikan kepada Microsoft, saya akan mengirim silang hasil apa pun di sini setelah saya kirimkan). Saya telah menggali file jejak ODBC antara kueri yang berfungsi (dengan komentar / pernyataan pernyataan tambahan) dan kueri yang tidak berfungsi. Perbedaan jejak mendasar diposting di bawah ini. Ini terjadi pada panggilan ke panggilan SQLExtendedFetch setelah semua diskusi SQLBindCol selesai. Panggilan gagal dengan kode kembali -1, dan utas induk kemudian memasuki SQLCancel. Karena kami dapat menghasilkan ini dengan driver Native Client dan Legacy ODBC, saya masih menunjuk ke beberapa masalah kompatibilitas di sisi server.
(clip)
MSSQLODBCTester 1664-1718 EXIT SQLBindCol with return code 0 (SQL_SUCCESS)
HSTMT 0x001EEA10
UWORD 16
SWORD 1 <SQL_C_CHAR>
PTR 0x03259030
SQLLEN 51
SQLLEN * 0x0326B820 (0)
MSSQLODBCTester 1664-1718 ENTER SQLExtendedFetch
HSTMT 0x001EEA10
UWORD 1 <SQL_FETCH_NEXT>
SQLLEN 1
SQLULEN * 0x032677C4
UWORD * 0x032679B0
MSSQLODBCTester 1664-1fd0 ENTER SQLCancel
HSTMT 0x001EEA10
MSSQLODBCTester 1664-1718 EXIT SQLExtendedFetch with return code -1 (SQL_ERROR)
HSTMT 0x001EEA10
UWORD 1 <SQL_FETCH_NEXT>
SQLLEN 1
SQLULEN * 0x032677C4
UWORD * 0x032679B0
DIAG [S1008] [Microsoft][ODBC SQL Server Driver]Operation canceled (0)
MSSQLODBCTester 1664-1fd0 EXIT SQLCancel with return code 0 (SQL_SUCCESS)
HSTMT 0x001EEA10
MSSQLODBCTester 1664-1718 ENTER SQLErrorW
HENV 0x001E7238
HDBC 0x001E7B30
HSTMT 0x001EEA10
WCHAR * 0x08BFFC5C
SDWORD * 0x08BFFF08
WCHAR * 0x08BFF85C
SWORD 511
SWORD * 0x08BFFEE6
MSSQLODBCTester 1664-1718 EXIT SQLErrorW with return code 0 (SQL_SUCCESS)
HENV 0x001E7238
HDBC 0x001E7B30
HSTMT 0x001EEA10
WCHAR * 0x08BFFC5C [ 5] "S1008"
SDWORD * 0x08BFFF08 (0)
WCHAR * 0x08BFF85C [ 53] "[Microsoft][ODBC SQL Server Driver]Operation canceled"
SWORD 511
SWORD * 0x08BFFEE6 (53)
MSSQLODBCTester 1664-1718 ENTER SQLErrorW
HENV 0x001E7238
HDBC 0x001E7B30
HSTMT 0x001EEA10
WCHAR * 0x08BFFC5C
SDWORD * 0x08BFFF08
WCHAR * 0x08BFF85C
SWORD 511
SWORD * 0x08BFFEE6
MSSQLODBCTester 1664-1718 EXIT SQLErrorW with return code 100 (SQL_NO_DATA_FOUND)
HENV 0x001E7238
HDBC 0x001E7B30
HSTMT 0x001EEA10
WCHAR * 0x08BFFC5C
SDWORD * 0x08BFFF08
WCHAR * 0x08BFF85C
SWORD 511
SWORD * 0x08BFFEE6
(clip)
Menambahkan kasing Microsoft Connect 10/12/2012:
Saya juga harus mencatat bahwa kami memang mencari rencana kueri untuk kueri yang berfungsi dan yang tidak berfungsi. Keduanya digunakan kembali secara tepat berdasarkan jumlah eksekusi. Menyiram paket yang di-cache dan menjalankan kembali tidak mengubah keberhasilan kueri.
sp_executesql
dan lihat apa yang terjadi.
select id, test_date from [big table] where serial_number = ..... order by test_date
- Saya hanya ingin tahu apakahSELECT *
ini berdampak negatif pada kinerja Anda. Jika Anda memiliki indeks nonclusteredtest_date
dan indeks berkerumunid
(dengan asumsi itu namanya), kueri ini harus dicakup oleh indeks nonclustered dan karenanya harus kembali cukup cepat