ประสิทธิภาพของ SQL Server ลดลงอย่างฉับพลัน


13

ฉันมี SQL Server 2005 ที่คาดเดาไม่ได้ว่าล่าช้าและฉันเกาหัวว่าทำไม แบบสอบถามที่ดำเนินการในไม่กี่วินาทีกำลังเปลี่ยนแผนและใช้เวลาไม่กี่นาที (สละเวลาในการสแกนเต็มตารางหรือสปูลดัชนี) ตอนนี้สิ่งแรกและชัดเจนที่สุดคือสถิติล้าสมัยทำให้เครื่องมือเพิ่มประสิทธิภาพสับสน แต่ฉันเชื่อว่านี่ไม่ใช่กรณี - ประการแรกเนื่องจากข้อมูลพื้นฐานไม่เปลี่ยนแปลงอย่างมีนัยสำคัญ (เช่นการเพิ่มข้อมูลหนึ่งวันบนข้อมูลหนึ่งปี มีอยู่ในตารางแล้ว) และอันดับที่สองเนื่องจากสถิติการสร้างอัตโนมัติและสถิติการอัปเดตอัตโนมัติเป็นจริงทั้งคู่ แต่เพิ่มประสิทธิภาพอยู่ในการสับสน; การรัน SQL ในโปรแกรมช่วยแนะนำการปรับแต่งให้CREATE STATISTICSคำสั่งหลายคอลัมน์มากมายซึ่งดูเหมือนว่าจะแก้ไขได้

ความคิดใดของกลยุทธ์ที่ฉันสามารถใช้เพื่อเข้าใกล้รากสาเหตุนี้ ทำไมสถิติ "ปกติ" ไม่เพียงพอ?

คำตอบ:


8

หากการรอเวลาสูงสุดของคุณคือ SOS_SCHEDULER_YIELD แสดงว่าคุณมีแรงกดดันต่อ CPU แต่นี่อาจเป็นผลมาจากสิ่งอื่นเช่นการออกแบบของคุณไม่เพียงพอสำหรับการสืบค้นของคุณ ฉันรู้ว่าคุณพูดว่าคุณกำลังเพิ่มข้อมูลเพียงหนึ่งวัน แต่คุณอาจมีจุดเปลี่ยน

คำถามของคุณมีการออกอย่างไร มันเป็น SQL แบบไดนามิกหรือไม่? คุณใช้กระบวนงานที่เก็บไว้หรือไม่ คุณใช้ sp_executesql หรือไม่ เป็นไปได้ไหมที่คุณมีกรณีของการดมพารามิเตอร์ การออกแบบฐานข้อมูลของคุณมีลักษณะอย่างไร ความสัมพันธ์ระหว่าง PK และ FK คืออะไร

คุณมีตัวอย่างของแผนดีหรือไม่? หากคุณสามารถกำหนดแผนที่ดีได้คุณสามารถใช้ตัวนำทางแผนบังคับให้แบบสอบถามดำเนินการตามวิธีที่ระบุ

คุณยกตัวอย่างของแผนการที่ดีแย่ไหม?

สุดท้ายไปรับสำเนาของ sp_whoIsActive ( http://whoisactive.com/ ) จาก Adam Machanic และใช้เพื่อพิจารณาเพิ่มเติมเกี่ยวกับการสืบค้นที่กำลังทำงานอยู่ และถ้าคุณต้องการที่จะสามารถจับเอาท์พุทจาก sp_whoIsActive ไปที่นี่http://www.littlekendra.com/2011/02/01/whoisactive/


มันเป็นโปรแกรมของบุคคลที่สามผมไม่มีการควบคุมเกินคีมาหรือ SQL ซึ่งเป็นที่น่ากลัวสวยจำนวนมากแบบสอบถาม (เช่นwhere col=(cast @var...)) และอาจจะมี@var '%'ฉันเพิ่งรับช่วงสองหรือสามสัปดาห์ที่ผ่านมาและต้องให้มันทำงานโดยทั่วไปจนกว่าจะถูกแทนที่ ขอบคุณสำหรับลิงค์ฉันจะให้มันหมุนวน
ออกุสตุส

การรอคอยครั้งต่อไปที่ยิ่งใหญ่ที่สุดหลังจากSOS_SCHEDULER_YIELDนั้นCXPACKETและsp_configure "max degree of parallelism", 1ดูเหมือนจะมี - สำหรับตอนนี้ - เคาะปัญหาทั้งสองบนหัว ขอบคุณ!
ออกุสตุส

+1 สำหรับลิงก์ไปยัง sp_whoIsActive
Jeff

8

จากMSDN :

"การแทรกการดำเนินงานเกิดขึ้นจากการขึ้นหรือลงจากคอลัมน์คีย์คอลัมน์ สถิติในการขึ้นหรือลงจากคอลัมน์คีย์เช่น IDENTITY หรือคอลัมน์เวลาประทับตามเวลาจริงอาจต้องการการอัปเดตสถิติบ่อยกว่าการเพิ่มประสิทธิภาพการสืบค้นแบบสอบถาม จำนวนแถวที่เพิ่มอาจมีขนาดเล็กเกินไปที่จะทริกเกอร์การอัปเดตสถิติหากสถิติไม่ใช่ข้อมูลล่าสุดและแบบสอบถามเลือกจากแถวที่เพิ่มล่าสุดสถิติปัจจุบันจะไม่มีการประมาณการเชิงการนับสำหรับค่าใหม่เหล่านี้ ส่งผลให้การประเมินความผิดพลาดของ cardinality ไม่ถูกต้องและประสิทธิภาพการสืบค้นช้า

ตัวอย่างเช่นแบบสอบถามที่เลือกจากวันที่สั่งซื้อล่าสุดจะมีการประเมินความผิดปกติของ cardinality ที่ไม่ถูกต้องหากสถิติไม่ได้รับการอัพเดตเพื่อรวมการประเมิน cardinality สำหรับวันที่สั่งซื้อล่าสุด

หลังจากการดำเนินการบำรุงรักษาให้ พิจารณาอัปเดตสถิติหลังจากดำเนินการตามขั้นตอนการบำรุงรักษาที่เปลี่ยนการกระจายข้อมูลเช่นตัดทอนตารางหรือทำการแทรกจำนวนมากของแถวขนาดใหญ่ สิ่งนี้สามารถหลีกเลี่ยงความล่าช้าในอนาคตในการประมวลผลแบบสอบถามในขณะที่แบบสอบถามรอการปรับปรุงสถิติอัตโนมัติ "

คุณอาจใช้ "EXEC sp_updatestats" เป็นครั้งคราวในระบบของคุณ (กำหนดเวลาสักครู่) หรือใช้ฟังก์ชัน STATS_DATE กับวัตถุทั้งหมดและดูว่าเมื่อใดที่สถิติของพวกเขาได้รับการปรับปรุงครั้งล่าสุดจริง ๆ และหากมีเวลามากเกินไปให้ใช้ UPDATE สถิติสำหรับวัตถุนั้น จากประสบการณ์ของฉันแม้จะเปิดใช้งานสถิติอัตโนมัติเรายังคงต้องอัปเดตสถิติเป็นครั้งคราวเนื่องจากการดำเนินการแทรกที่ไม่ได้เรียกใช้การอัปเดตอัตโนมัติ

ในการเพิ่มรหัสส่วนตัวของฉัน (ใช้ในงานประจำสัปดาห์ที่สร้างงบแบบไดนามิกสำหรับการปรับปรุงสถิติ):

select distinct
        'update statistics [' + stats.SchemaName + '].[' + stats.TableName + ']'
            + case when stats.RowCnt > 50000 then ' with sample 30 percent;'
            else 
                ';' end
        as UpdateStatement
    from (
        select
            ss.name SchemaName,
            so.name TableName,
            so.id ObjectId,
            st.name AS StatsName, 
            STATS_DATE(st.object_id, st.stats_id) AS LastStatisticsUpdateDate
            , si.RowModCtr
            , (select case si2.RowCnt when 0 then 1 else si2.RowCnt end from sysindexes si2 where si2.id = si.id and si2.indid in (0,1)) RowCnt
        from sys.stats st
            join sysindexes si on st.object_id = si.id and st.stats_id = si.indid
            join sysobjects so on so.id = si.id and so.xtype = 'U' --user table
            join sys.schemas ss on ss.schema_id = so.uid
    ) stats
    where cast(stats.RowModCtr as float)/cast(stats.RowCnt as FLOAT)*100 >= 10 --more than 10% of the rows have changed
    or ( --update statistics that were not updated for more than 3 months (and rows no > 0)
        datediff(month, stats.LastStatisticsUpdateDate, getdate()) >= 3
        and stats.RowCnt > 0
    )

ที่นี่ฉันได้รับวัตถุทั้งหมดที่ไม่ได้อัพเดตสถิติเป็นเวลามากกว่า 3 เดือนหรือตั้งแต่สถิติล่าสุดมีการเปลี่ยนแปลงมากกว่า 10% ของแถว


อืมเหตุการณ์การรอคอยอันดับต้น ๆ ของฉันคือSOS_SCHEDULER_YIELDแต่ฉันไม่สามารถบอกได้ในตอนนี้ว่าเป็นเพราะแผนการที่ไม่ดีหรือกล่อง (ตัวประมวลผล 2 โปรเซสเซอร์ 4G RAM) อายุ 6 ขวบนี้เพิ่งโหลดมากเกินไปจริง ๆ และฉันก็ ผ่านจุดเปลี่ยนไปแล้ว
ออกุสตุส

แทนที่จะเรียกใช้แบบสอบถามเพื่อสร้างคำสั่ง UPDATE และเรียกใช้ด้วยตนเองคุณสามารถใช้เคอร์เซอร์ตามคำสั่งที่เลือกนั้นเพื่อวนรอบผลลัพธ์ที่เรียกใช้โดยใช้การเรียกไปยัง sp_executesql ซึ่งเป็นวิธีที่คุณสามารถเรียกใช้ได้โดยอัตโนมัติ (เช่นเป็นส่วนหนึ่ง ของแผนการบำรุงรักษาข้ามคืน (หรือช่วงเวลาที่เงียบอื่น ๆ )
David Spillett

@ David: นี่คือสิ่งที่ฉันทำในงานประจำสัปดาห์ :) ฉันเพิ่งฟอร์แมตรูปแบบที่แตกต่างกันเพื่อให้ Gaius เห็นผลลัพธ์ที่ฉันใช้ สคริปต์เริ่มต้นนั้นดูน่าเกลียดและยาวเกินไป ขอบคุณสำหรับความช่วยเหลือในการจัดรูปแบบ! คุณช่วยส่งฉันไปสอนการฟอร์แมตได้ไหมเพราะฉันไม่รู้วิธีทำให้โค้ดดูดีที่นี่ ขอบคุณ!
Marian

มีลิงก์ "ความช่วยเหลือในการจัดรูปแบบ" ในหน้าจอ "แก้ไขคำตอบ" และเป็นไอคอนทางด้านขวาเหนือช่องคำตอบเริ่มต้นในหน้าคำถามหลักซึ่งแสดงรายการไวยากรณ์ของ markdown ที่เว็บไซต์เหล่านี้รองรับ
David Spillett

3
สถิติการอัปเดตอัตโนมัติทริกเกอร์ที่ 20% + 500 แถวไม่ใช่ 10%
mrdenny

3

ฉันเดาว่าตารางอย่างน้อยหนึ่งตารางของคุณมีขนาดใหญ่พอที่จะไม่ตี 20% ของการเปลี่ยนแปลงที่จำเป็นเพื่อช่วยทำเครื่องหมายสถิติปัจจุบันว่าเป็นข้อมูลเก่าดังนั้นสถิติการอัปเดตอัตโนมัติจะเริ่มขึ้นและยังมีการอัปเดตมากพอ ) ว่าการมีสถิติล่าสุดจะช่วยได้มาก ฉันพบสิ่งเดียวกันเมื่อเร็ว ๆ นี้ในสภาพแวดล้อมเฉพาะหลังจากอัปเกรดจาก SQL 2000 เป็น SQL 2008

นอกเหนือจากเว็บไซต์อื่น ๆ ที่กล่าวถึงในคำตอบข้างต้นฉันขอแนะนำให้ตรวจสอบแหล่งข้อมูลออนไลน์ต่อไปนี้

1) Red-Gate มี ebooks ฟรีให้ดาวน์โหลดมากมายรวมถึง "SQL Server Statistics" โดย Holger Schmeling ซึ่งคุณจะพบคำพูดต่อไปนี้:

http://www.red-gate.com/our-company/about/book-store/

"ตารางที่มีมากกว่า 500 แถวอย่างน้อย 20% ของข้อมูลคอลัมน์จะต้องมีการเปลี่ยนแปลงเพื่อทำให้สถิติที่เชื่อมโยงถูกต้อง"

2) SQL Sentry มีเครื่องมือ Plan Explorer ฟรีที่ช่วยติดตามปัญหาภายในแผน SQL เช่นการประเมินจำนวนแถวมากหรือน้อยเกินไปเมื่อเปรียบเทียบกับจำนวนแถวจริงสำหรับตารางที่กำหนดในแบบสอบถาม เพียงบันทึกแผนการดำเนินการจริงจาก SSMS แล้วเดินผ่านส่วนต่าง ๆ ของแผนโดยใช้ Plan Explorer ไม่ใช่ว่าข้อมูลนั้นไม่มีอยู่ใน SSMS โดยใช้แผนการดำเนินการกราฟิก แต่เครื่องมือจาก SQL Sentry ทำให้ดูได้ง่ายขึ้นมาก

http://www.sqlsentry.com/plan-explorer/sql-server-query-view.asp

3) ตรวจสอบวันที่ปรับปรุงสถิติด้วยตัวคุณเองสำหรับตารางในแบบสอบถามที่คุณสนใจในการใช้ STATS_DATE () คุณสามารถค้นหาข้อความด่วนเพื่อรับสถิติที่เก่าที่สุดโดยใช้แบบสอบถามที่พบในการสนทนาต่อไปนี้

http://blog.sqlauthority.com/2010/01/25/sql-server-find-statistics-update-date-update-statistics/

ฉันหวังว่านี่จะช่วยได้!

ฉันคิดว่าคุณจะสนุกกับหนังสือจาก Red-Gate เป็นพิเศษ!

เจฟฟ์


ขอบคุณฉันจะทำงานผ่านสิ่งเหล่านั้น ฉันเป็น Oracle DBA ส่วนใหญ่ที่สืบทอดระบบนี้ (แม้ว่าฉันจะไม่ได้รับอคติต่อ SQL Server เลยจากสิ่งที่ฉันเห็นตั้งแต่ปี 2548 เป็นแพลตฟอร์มที่มีความสามารถมากฉันก็ไม่รู้เหมือนกันว่าฉันรู้จัก Oracle) .
ออกุสตุส
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.