เรากำลังใช้ SQL Server 2008 R2 และมีตารางที่มีขนาดใหญ่มาก (100M + แถว) ที่มีดัชนี id หลักและdatetimeคอลัมน์ที่มีดัชนีที่ไม่เป็นคลัสเตอร์ เราจะเห็นพฤติกรรมลูกค้า / เซิร์ฟเวอร์บางสูงผิดปกติขึ้นอยู่กับการใช้งานของนั้นorder byข้อโดยเฉพาะในคอลัมน์วันที่และเวลาการจัดทำดัชนี
ฉันอ่านข้อความต่อไปนี้: /programming/1716798/sql-server-2008-ordering-by-datetime-is-too-slow แต่มีอะไรเกิดขึ้นกับไคลเอนต์ / เซิร์ฟเวอร์มากกว่าสิ่งที่เป็น เริ่มอธิบายที่นี่
หากเราเรียกใช้แบบสอบถามต่อไปนี้ (แก้ไขเพื่อป้องกันเนื้อหาบางส่วน):
select *
from [big table]
where serial_number = [some number]
order by test_date desc
แบบสอบถามหมดเวลาทุกครั้ง ใน SQL Server Profiler แบบสอบถามที่ดำเนินการจะมีลักษณะเช่นนี้กับเซิร์ฟเวอร์:
exec sp_cursorprepexec @p1 output,@p2 output,NULL,N'select * .....
ตอนนี้ถ้าคุณปรับเปลี่ยนแบบสอบถามให้พูดสิ่งนี้:
declare @temp int;
select * from [big table]
where serial_number = [some number]
order by test_date desc
Profiler ของเซิร์ฟเวอร์ SQL แสดงแบบสอบถามที่ดำเนินการซึ่งมีลักษณะเช่นนี้ไปยังเซิร์ฟเวอร์และจะทำงานทันที:
exec sp_prepexec @p1 output, NULL, N'declare @temp int;select * from .....
ตามความเป็นจริงคุณสามารถใส่ความคิดเห็นที่ว่างเปล่า ('-;') แทนข้อความประกาศที่ไม่ได้ใช้และได้รับผลลัพธ์เดียวกัน ดังนั้นในตอนแรกเราได้ชี้ไปที่ตัวประมวลผลล่วงหน้าของ sp เป็นสาเหตุของปัญหานี้ แต่ถ้าคุณทำสิ่งนี้:
select *
from [big table]
where serial_number = [some number]
order by Cast(test_date as smalldatetime) desc
มันทำงานได้ทันทีเช่นกัน (คุณสามารถส่งเป็นdatetimeประเภทอื่นได้) ส่งคืนผลลัพธ์เป็นมิลลิวินาที และ profiler แสดงการร้องขอไปยังเซิร์ฟเวอร์ดังนี้:
exec sp_cursorprepexec @p1 output, @p2 output, NULL, N'select * from .....
ดังนั้นจึงค่อนข้างแยกsp_cursorprepexecขั้นตอนจากสาเหตุเต็มของปัญหา เพิ่มข้อเท็จจริงนี้ที่sp_cursorprepexecถูกเรียกเมื่อไม่มีการใช้ 'คำสั่งซื้อ' และผลลัพธ์จะถูกส่งคืนทันที
เราพบปัญหานี้กันสักหน่อยแล้วและฉันเห็นปัญหาที่คล้ายกันซึ่งโพสต์จากคนอื่น ๆ แต่ก็ไม่มีใครทำลายมันลงไปถึงระดับนี้
มีคนอื่นเห็นพฤติกรรมนี้หรือไม่? ใครบ้างมีทางออกที่ดีกว่าการวาง SQL ที่ไม่มีความหมายไว้ข้างหน้าคำสั่ง select เพื่อเปลี่ยนพฤติกรรม? เนื่องจาก SQL Server ควรเรียกใช้คำสั่งโดยหลังจากรวบรวมข้อมูลแล้วดูเหมือนว่านี่เป็นจุดบกพร่องในเซิร์ฟเวอร์ที่ยังคงมีอยู่เป็นเวลานาน เราพบว่าพฤติกรรมนี้สอดคล้องกันทั่วทั้งตารางขนาดใหญ่ของเราและสามารถทำซ้ำได้
การแก้ไข:
ฉันควรเพิ่มการใส่forceseekเข้าไปยังทำให้ปัญหาหายไป
ฉันควรเพิ่มเพื่อช่วยให้ผู้ค้นหาข้อผิดพลาดการหมดเวลา ODBC คือ: [Microsoft] [โปรแกรมควบคุม ODBC SQL Server Server] การดำเนินการถูกยกเลิก
เพิ่ม 10/12/2012: ยังคงตามหาสาเหตุที่แท้จริง (พร้อมกับสร้างตัวอย่างเพื่อมอบให้กับ Microsoft ฉันจะข้ามโพสต์ผลลัพธ์ใด ๆ ที่นี่หลังจากที่ฉันส่ง) ฉันขุดลงไปในไฟล์ติดตาม ODBC ระหว่างคิวรี่ที่ใช้งานได้ (พร้อมกับเพิ่มข้อคิดเห็น / ประกาศคำสั่ง) และคิวรี่ที่ไม่ทำงาน ความแตกต่างพื้นฐานการติดตามถูกโพสต์ด้านล่าง มันเกิดขึ้นกับการเรียก SQLExtendedFetch โทรหลังจากการสนทนา SQLBindCol ทั้งหมดเสร็จสมบูรณ์ การเรียกล้มเหลวด้วยโค้ดส่งคืน -1 จากนั้นเธรดหลักจะเข้าสู่ SQLCancel เนื่องจากเราสามารถผลิตสิ่งนี้ได้ทั้งกับ Native Client และไดรเวอร์ ODBC ดั้งเดิมฉันยังคงชี้ประเด็นความเข้ากันได้ทางฝั่งเซิร์ฟเวอร์
(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)
เพิ่มเคส Microsoft Connect 10/12/2012:
ฉันควรทราบด้วยว่าเราได้ค้นหาแผนแบบสอบถามสำหรับทั้งแบบสอบถามการทำงานและการไม่ทำงาน พวกเขาทั้งสองนำมาใช้ใหม่อย่างเหมาะสมตามจำนวนการดำเนิน การล้างแผนแคชและการเรียกใช้ใหม่จะไม่เปลี่ยนความสำเร็จของแบบสอบถาม
sp_executesqlแล้วดูว่าเกิดอะไรขึ้น
select id, test_date from [big table] where serial_number = ..... order by test_date- ฉันแค่สงสัยว่าสิ่งSELECT *นั้นมีผลเสียต่อการแสดงของคุณหรือไม่ หากคุณมีดัชนีแบบ nonclusteredtest_dateและดัชนีแบบคลัสเตอร์บนid(สมมติว่าเป็นสิ่งที่เรียกว่า) การสืบค้นนี้ควรถูกครอบคลุมโดยดัชนีแบบ nonclustered นั้นดังนั้นจึงควรกลับอย่างรวดเร็ว