มันอาจเกิดขึ้นได้ว่าข้อมูลจำนวนเล็กน้อยมีจำนวน จำกัด ใน SQL Server เพื่อบังคับแผนอื่นหรืออะไรทำนองนั้น สิ่งนี้ไม่น่าเป็นไปได้ แต่ความจริงที่ว่าแผ่นดิสก์ของคุณดูเหมือนจะอยู่ภายใต้การรับผิดชอบอย่างหนักทำให้ฉันได้ข้อสรุปอื่น
มีเหตุผลพื้นฐาน 2 ประการที่เป็นไปได้สำหรับการชะลอตัวของคุณ
- คุณอัปเกรดระบบของคุณและรีบูตระบบ
- คุณโหลดข้อมูลจำนวนมากในนั้น
ลองดูที่ส่วนที่ 1
อาจเป็นเพราะการกำหนดค่า SQL Server ของคุณอาจจะเสีย ซึ่งอาจทำให้เกิดปัญหาร้ายแรงเกี่ยวกับความเร็วของเซิร์ฟเวอร์และการใช้งานดิสก์
โปรดตรวจสอบในการตั้งค่าเซิร์ฟเวอร์พื้นฐานของคุณเป็นครั้งแรก ผู้ตั้งค่าพื้นฐานmax server memory
, affinity I/O mask
, และaffinity mask
คุณอาจจะต้องเปิดใช้งานตัวเลือกขั้นสูงโดยใช้max degree of parallelism
show advanced options
นี่คือสคริปต์ที่สมบูรณ์:
-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'
เปรียบเทียบผลลัพธ์กับค่าเอกสารของคุณในขั้นตอนการติดตั้ง พวกเขายังคงเหมือนเดิมหรือไม่
อาจมีสาเหตุหลายประการที่เซิร์ฟเวอร์ของคุณมีพฤติกรรมแปลก ๆ ปกติแล้วฉันจะพนันว่าคุณmax server memory
ผิด สิ่งนี้จะทำให้ SQL Server ของคุณสลับหน้าข้อมูลอย่างถาวร เขาไม่สามารถเก็บทุกอย่างไว้ในความทรงจำของเขาได้ ซึ่งหมายความว่าเขาต้องอ่านหน้าจากแผ่นดิสก์อัปเดตเขียนมันกลับทันที หากมีการอัปเดตอื่นมาพร้อมและใช้หน้าเดียวกันสำหรับการอัปเดตจะไม่สามารถอ่านได้จากหน่วยความจำ เซิร์ฟเวอร์ต้องการอ่านอีกครั้งจากแผ่นดิสก์แทน เพียงแค่แลกเปลี่ยน ...
ปัญหาอื่นอาจเป็นความสัมพันธ์ที่สูงถึงดิสก์หรือกระบวนการ ถ้าคุณใช้เซิร์ฟเวอร์ที่ใช้ร่วมกัน (SQL Server + บริการอื่น ๆ ) กับดิสก์เฉพาะสำหรับ SQL Server (ซึ่งอาจเป็นกรณีที่ไม่ค่อยพบ แต่อาจเป็นได้) นี่อาจเป็นปัญหาของคุณ โดยปกติเซิร์ฟเวอร์ของคุณเคยมีตัวอย่าง 3 cpus สำหรับกระบวนการและอีกหนึ่งตัวสำหรับ I / O อีก 12 ซีพียูใช้สำหรับบริการอื่น ๆ ในกรณีนี้รูปแบบความสัมพันธ์ของคุณผิดและใช้ตัวอย่างเช่นการกำหนดค่าอัตโนมัติ นี่หมายความว่าเซิร์ฟเวอร์ของคุณใช้ 16 คอร์ทั้งหมดสำหรับกระบวนการและ I / O แบบไดนามิก หากคุณมีกระบวนการขนาดใหญ่ที่ทำงานอยู่พวกเขาสามารถวางแผ่นดิสก์จำนวนมากซึ่งไม่สามารถจัดการได้ แต่ในความเป็นจริงฉันไม่เชื่อว่านี่เป็นกรณีของคุณ มันจะเร็วขึ้น (แม้ว่าจะเป็นเพียงเล็กน้อย) หากเป็นไปได้ แต่กรณีของคุณช้าลง
ปัญหาอื่นอาจเกิดจากการขนานที่สูงเกินไป ซึ่งหมายความว่าคุณมีเธรดจำนวนมากที่ไม่ทำงานบนเคียวรีบางส่วน สิ่งนี้อาจทำให้ช้าลงอย่างมากหากความขนานไม่ทำงานตามที่คาดไว้ แต่นี่จะไม่อธิบาย I / O สูงทั้งหมดของคุณ
ทีนี้ลองดูส่วนที่ 2 ด้วย
คุณโหลดหลายแถวเข้าสู่ระบบของคุณ แม้ว่านี่จะเป็นงานปกติ แต่ก็สามารถเพิ่มขีด จำกัด ที่แผนแบบสอบถามของคุณเพิ่มขึ้น อาจเป็นได้ว่าในกรณีที่การแทรกของคุณร่วมกับ SQL Server ก่อให้เกิดพฤติกรรมนี้
คุณพูดถึงว่าคุณพยายามย้ายดัชนีไปยังแผ่นดิสก์อื่นซึ่งดูเหมือนว่าจะช่วยได้ นี่อาจเป็นสิ่งที่เกิดขึ้นกับความจริงที่ว่าคุณแบ่งการโหลดลงบนดิสก์สองแผ่น
อาจเป็นได้ว่าดัชนีของคุณแตกหัก, แผนของคุณแตกหักหรือว่าสถิติของคุณล้าสมัยไปแล้ว
1. ให้ตรวจสอบสถิติอัปเดตล่าสุด
คุณสามารถทำได้ด้วยตนเองผ่านอินเทอร์เฟซสำหรับองค์ประกอบทางสถิติแต่ละรายการ ซึ่งจะเป็นความเจ็บปวด หรือคุณสามารถลองใช้รหัสนี้:
SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes
สิ่งนี้จะให้ข้อมูลที่สมบูรณ์กับแต่ละดัชนี (และฮีป) และสถิติเบื้องหลัง แม้ว่าคุณจะรันsp_updatestats
มันไม่ได้หมายความว่าสถิติได้รับการปรับปรุง ส่วนเมื่อมีการอัพเดทค่อนข้างยุ่งยากแม้ว่าคุณจะทำงานsp_updatestats
หรือแม้กระทั่งถ้าauto update statistics
มีการเปิดใช้สถิติที่จะไม่ได้รับการปรับปรุงเพียงในเวลา นี่คือบางจุดที่ขอบเมื่อต้องการการปรับปรุง / สร้าง:
- ตารางว่างรับหนึ่งแถวขึ้นไป
- ตารางที่มีแถวมากกว่า 500 แถวจะอัปเดตเพิ่มเติม 20% + 500 แถวและมีการแทรกเกิดขึ้นในภายหลัง
- เมื่อมีการเปลี่ยนแปลง 500 แถวในตารางที่มีน้อยกว่า 500 แถว
ซึ่งหมายความว่าสถิติของคุณอาจล้าสมัยแม้ว่าคุณจะรันการอัพเดทก็ตาม
คุณสามารถดูคำถามข้างต้น หากคุณพบสถิติเก่า ๆ ในบางตารางคุณอาจต้องการเรียกใช้การปรับปรุงสถิติด้วยตนเองสำหรับตารางนี้:
UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN
หลังจากนั้นคุณอาจต้องการให้เซิร์ฟเวอร์ของคุณเตะในลาเพื่อทิ้งแผนเก่าทั้งหมด
DBCC FREEPROCCACHE
หากคุณต้องการล้างแคชทั้งหมดคุณอาจต้องการเรียกใช้สิ่งนี้แทน:
DBCC FREESYSTEMCACHE ('ALL')
สิ่งนี้จะทำความสะอาดแคชทั้งหมดไม่ใช่เฉพาะแคชแผน ปกติฉันจะเตือนเพื่อใช้สิ่งนี้กับเซิร์ฟเวอร์ที่ใช้งานจริงในขั้นตอนการผลิต แต่ในขณะที่เซิร์ฟเวอร์ของคุณไม่ทำงานคุณไม่สามารถทำร้ายพวกเขามากเกินไป อาจช้าลงในบางวินาทีอาจ 1-2 นาทีตามที่เขาต้องการสร้างแคชทั้งหมด แต่หลังจากนั้นเขาควรรันด้วยแผนการที่ถูกต้อง
เหตุผลอื่นอาจเป็นดัชนีแยกส่วนโดยสิ้นเชิง สามารถตรวจสอบได้บนเซิร์ฟเวอร์ทั้งหมดโดยใช้คำสั่งนี้:
SELECT *
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)
หากการแตกแฟรกเมนต์สูงมากคุณอาจต้องจัดระเบียบใหม่ (การแตกแฟรกเมนต์ <20%) หรือสร้างใหม่ทั้งหมด (> 20%) การทำเช่นนี้อาจทำให้เกิดแรงกดดันต่อแผ่นดิสก์ของคุณและทำให้เกิดปัญหา ในทางกลับกันหากดัชนีเป็นสิ่งที่ไม่ดีมันอาจจะช่วยได้ในท้ายที่สุดมากกว่าจะเป็นอันตราย
นอกเหนือจากเหตุผลสองข้อนั้นยังอาจมีปัญหาที่สาม
อาจเป็นเพราะเซิร์ฟเวอร์ของคุณได้รับการกำหนดค่าไว้คุณอาจยังไม่ได้เปลี่ยนรหัสใด ๆ ในเวลานี้เพิ่มเพียงไม่กี่แถว สถิติทั้งหมดได้รับการอัพเดตและแคชทั้งหมดจะถูกสร้างใหม่ ดัชนีทั้งหมดของคุณจะถูกจัดระเบียบใหม่ในแบบที่คุณต้องการ แต่ยังคง - ไม่มีอะไรทำงาน อาจเป็นไปได้ว่าคุณมีหน่วยความจำถึงขีด จำกัด ในกระบวนการของคุณ บางทีคุณอาจต้องการมากกว่านี้ คุณสามารถตรวจสอบว่ามีกระบวนการใดบ้างที่พยายามรับหน่วยความจำมากกว่าที่คุณมี
คุณสามารถตรวจสอบได้โดยใช้คำสั่งนี้:
SELECT * FROM sys.dm_exec_query_memory_grants
มันจะให้รายการของเซสชันทั้งหมดที่ใช้หน่วยความจำ อาจมีข้อความค้นหาบางส่วนที่ยังรอรับหน่วยความจำอยู่ สามารถกรองแบบสอบถามเหล่านั้นได้อย่างง่ายดาย granted_memory_kb IS NULL
ทุกครั้งที่ นี่คือเซสชันที่ร้องขอหน่วยความจำ แต่ไม่ได้รับ อีกสิ่งหนึ่งอาจเป็นหน่วยความจำที่ได้รับซึ่งอาจต่ำ คุณสามารถเปรียบเทียบคอลัมน์ด้วยrequested_memory_kb
granted_memory_kb
ร้องขอแสดงจำนวนหน่วยความจำที่กระบวนการต้องการให้ทำงานได้ดีที่สุดในขณะที่ให้สิทธิ์แสดงหน่วยความจำที่เปิดใช้งานสำหรับกระบวนการ หากกระบวนการต้องการใช้งาน 2GB แต่ได้รับเพียง 2MB ... คุณอาจได้รับด้วยตัวเอง ;-)
อีกวิธีคือตรวจสอบRESSOURCE_SEMAPHORE
:
SELECT * FROM sys.dm_exec_query_resource_semaphore
คุณสามารถใช้เวลาดูที่และwaiter_count
grantee_count
หากพนักงานเสิร์ฟมีค่ามากกว่า 0 แสดงว่าคุณมีแรงกดดันต่อความจำของคุณซึ่งอาจทำให้เกิดการแลกเปลี่ยนและอาจทำให้เกิดแรงกดดันต่อดิสก์ที่คุณเห็นในปอด