SQL Server 2008 R2 kullanıyoruz ve birincil kimlik dizinine sahip çok büyük (100M + satır) bir tablo ve datetimekümelenmemiş bir dizine sahip bir sütun var. Biz kullanımına dayanan bazı oldukça sıradışı istemci / sunucu davranışlarla karşılaşır order bymaddede özel olarak bir üzerinde endeksli datetime sütuna .
Aşağıdaki yazıyı okudum: /programming/1716798/sql-server-2008-ordering-by-datetime-is-too-slow ama istemci / sunucu ile olandan daha fazla şey var burada açıklanmaya başlayın.
Aşağıdaki sorguyu çalıştırırsak (bazı içeriği korumak için düzenlenir):
select *
from [big table]
where serial_number = [some number]
order by test_date desc
Sorgu her seferinde zaman aşımına uğruyor. SQL Server Profiler'da yürütülen sorgu sunucuya şöyle görünür:
exec sp_cursorprepexec @p1 output,@p2 output,NULL,N'select * .....
Şimdi sorguyu olarak değiştirirseniz şunu söyleyin:
declare @temp int;
select * from [big table]
where serial_number = [some number]
order by test_date desc
SQL Server Profiler, çalıştırılan sorguyu sunucuya benzer şekilde gösterir ve anında çalışır:
exec sp_prepexec @p1 output, NULL, N'declare @temp int;select * from .....
Nitekim kullanılmayan bir beyanname yerine boş bir yorum ('-;') bile ekleyebilir ve aynı sonucu alabilirsiniz. Bu yüzden başlangıçta sp ön işlemcisine bu sorunun temel nedeni olarak işaret ediyorduk, ancak bunu yaparsanız:
select *
from [big table]
where serial_number = [some number]
order by Cast(test_date as smalldatetime) desc
Anında da çalışır (başka bir datetimetür olarak yayınlayabilirsiniz), sonucu milisaniye olarak döndürür. Profiler sunucuya isteği şu şekilde gösterir:
exec sp_cursorprepexec @p1 output, @p2 output, NULL, N'select * from .....
Böylece sp_cursorprepexecprosedürü sorunun tam nedeninden bir şekilde hariç tutar . Buna, sp_cursorprepexec'sipariş etme' kullanılmadığında da çağrılması ve sonuç anında geri dönmesi gerçeğini de ekleyin .
Bu sorun için biraz araştırdık ve başkalarından benzer sorunlar görüyorum, ancak bu seviyeye ulaşan hiçbir şey yok.
Peki diğerleri bu davranışa tanık oldu mu? Davranışı değiştirmek için select deyimi önüne anlamsız SQL koymaktan daha iyi bir çözümü var mı? Veri toplandıktan sonra SQL Server'ın siparişi çağırması gerektiği için, bu sunucuda uzun süre devam eden bir hata gibi görünüyor. Bu davranışın büyük tablolarımızın çoğunda tutarlı olduğunu gördük ve tekrarlanabilir.
Düzenlemeler:
Ben de eklemek koyarak forceseekda sorunu ortadan kaldırır eklemek gerekir .
Arama yardımcı olmak için eklemeniz gerekir, ODBC zaman aşımı hatası atıldı: [Microsoft] [ODBC SQL Server sürücüsü] İşlem iptal edildi
Eklendi 10/12/2012: Hala kök neden avlanıyor, (Microsoft'a vermek için bir örnek oluşturduktan sonra, gönderdikten sonra burada herhangi bir sonucu göndereceğim). ODBC izleme dosyasına (eklenen bir açıklama / beyan deyimi ile) bir çalışma sorgusu ve çalışmayan sorgu arasında kazma edilmiştir. Temel iz farkı aşağıda belirtilmiştir. Tüm SQLBindCol tartışmaları tamamlandıktan sonra SQLExtendedFetch çağrısında oluşur. Çağrı dönüş kodu -1 ile başarısız olur ve daha sonra üst iş parçacığı SQLCancel girer. Bunu hem Yerel İstemci hem de Eski ODBC sürücüleri ile üretebildiğimiz için, hala sunucu tarafında bazı uyumluluk sorununa işaret ediyorum.
(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)
12/12/2012 Microsoft Connect davası eklendi:
Ayrıca, hem işleyen hem de çalışmayan sorgular için sorgu planları baktım dikkat etmeliyim. Her ikisi de infaz sayısına göre uygun şekilde yeniden kullanılır. Önbelleğe alınmış planları yıkamak ve yeniden çalıştırmak, sorgunun başarısını değiştirmez.
sp_executesqlve ne olduğunu görün.
select id, test_date from [big table] where serial_number = ..... order by test_date- sadeceSELECT *performansınız üzerinde olumsuz bir etkisi olup olmadığını merak ediyorum . Kümelenmemiş bir dizininiztest_dateve bir kümelenmiş dizininiz varsaid(bu adın ne olduğunu varsayarak), bu sorgu bu kümelenmemiş dizin tarafından kapsanmalı ve bu nedenle oldukça hızlı bir şekilde dönmelidir