นี่เป็นอาการของเซิร์ฟเวอร์ที่โอเวอร์โหลดหรือไม่


12

ฉันพยายามวินิจฉัยช้าลงในแอปพลิเคชัน สำหรับสิ่งนี้ฉันได้บันทึกกิจกรรมเพิ่มเติมของ SQL Server แล้ว

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

เวลาดำเนินการของโพรซีเดอร์ที่เก็บแตกต่างกันไป การประมวลผลของโพรซีเดอร์ที่เก็บไว้นี้ส่งคืนเป็นจำนวนมากใน <1s:

ป้อนคำอธิบายรูปภาพที่นี่

และสำหรับถัง"เร็ว"นั้นมันน้อยกว่า 1 วินาทีมาก จริง ๆ แล้วประมาณ 90 ms:

ป้อนคำอธิบายรูปภาพที่นี่

แต่มีหางยาวของผู้ใช้ที่ต้องรอ 2 วินาที, 3 วินาที, 4s วินาที บางคนต้องรอ 12 วินาที, 13 วินาที, 14 วินาที จากนั้นก็มีวิญญาณที่น่าสงสารจริงๆที่ต้องรอ 22s, 23s, 24s

และหลังจาก 30s, โปรแกรมไคลเอนต์ให้ขึ้นยกเลิกแบบสอบถามและผู้ใช้ต้องรอ30 วินาที

สหสัมพันธ์เพื่อค้นหาสาเหตุ

ดังนั้นฉันจึงพยายามที่จะมีความสัมพันธ์:

  • ระยะเวลาและตรรกะอ่าน
  • ระยะเวลาเทียบกับการอ่านทางกายภาพ
  • ระยะเวลาเทียบกับเวลา cpu

และดูเหมือนจะไม่มีความสัมพันธ์ใด ๆ ; ดูเหมือนจะไม่มีสาเหตุ

  • ระยะเวลาและตรรกะอ่าน : ไม่ว่าจะเป็นเล็ก ๆ น้อย ๆ หรือจำนวนมากอ่านตรรกะระยะเวลายังคงผันผวน :

    ป้อนคำอธิบายรูปภาพที่นี่

  • ระยะเวลาและการอ่านทางกายภาพ : แม้ว่าการสืบค้นจะไม่ได้รับบริการจากแคชและจำเป็นต้องมีการอ่านจำนวนมาก แต่จะไม่ส่งผลต่อระยะเวลา:

    ป้อนคำอธิบายรูปภาพที่นี่

  • ระยะเวลาเทียบกับเวลาของ cpu : ไม่ว่าแบบสอบถามจะใช้เวลา 0 วินาทีของ CPU หรือเต็ม 2.5s ของเวลา CPU ระยะเวลามีความแปรปรวนเท่ากัน

    ป้อนคำอธิบายรูปภาพที่นี่

โบนัส : ฉันสังเกตว่าระยะเวลา v การอ่านทางกายภาพและระยะเวลา v เวลา CPUดูคล้ายกันมาก นี่เป็นการพิสูจน์ว่าฉันพยายามเชื่อมโยงเวลาของ CPU กับการอ่านแบบฟิสิคัล:

ป้อนคำอธิบายรูปภาพที่นี่

ปรากฎว่าการใช้งาน CPU จำนวนมากมาจาก I / O ใครจะรู้!

ดังนั้นหากไม่มีอะไรเกี่ยวกับการดำเนินการสืบค้นที่สามารถอธิบายความแตกต่างในเวลาดำเนินการนั่นหมายความว่าเป็นสิ่งที่ไม่เกี่ยวข้องกับ CPU หรือฮาร์ดไดรฟ์หรือไม่

หาก CPU หรือฮาร์ดไดรฟ์เป็นคอขวด มันจะไม่ใช่คอขวดเหรอ?

ถ้าเราตั้งสมมติฐานว่ามันเป็นซีพียูที่เป็นคอขวด CPU นั้นใช้พลังงานน้อยสำหรับเซิร์ฟเวอร์นี้:

  • ถ้าเช่นนั้นการประมวลผลโดยใช้เวลา CPU จะใช้เวลานานกว่าหรือไม่
  • เนื่องจากพวกเขาต้องทำกับผู้อื่นโดยใช้ซีพียูที่โอเวอร์โหลด?

ในทำนองเดียวกันสำหรับฮาร์ดไดรฟ์ หากเราตั้งสมมติฐานว่าฮาร์ดไดรฟ์เป็นคอขวด ฮาร์ดไดรฟ์มีการสุ่มใส่พอสำหรับเซิร์ฟเวอร์นี้ไม่เพียงพอ:

  • ถ้าอย่างนั้นการประหารชีวิตโดยใช้การอ่านเชิงกายภาพจะใช้เวลานานกว่ากันไหม?
  • เนื่องจากพวกเขาต้องทำกับผู้อื่นโดยใช้ I / O ฮาร์ดไดรฟ์ที่โอเวอร์โหลด

ขั้นตอนการจัดเก็บตัวเองไม่ได้ดำเนินการหรือต้องมีการเขียน

  • โดยปกติแล้วจะส่งคืน 0 แถว (90%)
  • บางครั้งมันจะส่งคืน 1 แถว (7%)
  • มันจะกลับมา 2 แถว (1.4%)
  • และในกรณีที่เลวร้ายที่สุดมันส่งคืนมากกว่า 2 แถว (ครั้งเดียวส่งคืน 12 แถว)

ดังนั้นจึงไม่เหมือนกับว่าจะส่งคืนปริมาณข้อมูลที่บ้า

การใช้งาน CPU ของเซิร์ฟเวอร์

ค่าเฉลี่ยการใช้งานตัวประมวลผลของเซิร์ฟเวอร์ประมาณ 1.8% โดยมีการขัดขวางเป็นครั้งคราวสูงถึง 18% - ดังนั้นจึงไม่ดูเหมือนว่า CPU จะมีปัญหา:

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นเซิร์ฟเวอร์ CPU จึงดูไม่โอเวอร์โหลด

แต่เซิร์ฟเวอร์เป็นเสมือน ...

มีอะไรนอกจักรวาล?

สิ่งเดียวที่เหลือที่ฉันจินตนาการได้ก็คือสิ่งที่อยู่นอกจักรวาลของเซิร์ฟเวอร์

  • ถ้ามันไม่ใช่ตรรกะอ่าน
  • และมันไม่ใช่การอ่านทางกายภาพ
  • และไม่ใช่การใช้งาน cpu
  • และไม่ใช่โหลดซีพียู

และไม่เหมือนว่ามันเป็นพารามิเตอร์ของกระบวนงานที่เก็บไว้ (เนื่องจากการออกแบบสอบถามเดียวกันด้วยตนเองและไม่ใช้เวลา 27 วินาที - ใช้เวลา ~ 0 วินาที)

สิ่งใดที่บัญชีสำหรับเซิร์ฟเวอร์บางครั้งใช้เวลา 30 วินาทีแทนที่จะเป็น 0 วินาทีเพื่อเรียกใช้ขั้นตอนการจัดเก็บที่รวบรวมไว้แบบเดียวกัน

  • ด่าน?

มันเป็นเซิร์ฟเวอร์เสมือน

  • โฮสต์โอเวอร์โหลดหรือไม่
  • VM อื่นบนโฮสต์เดียวกัน

การผ่านเหตุการณ์ที่เพิ่มขึ้นของเซิร์ฟเวอร์ ไม่มีสิ่งใดเกิดขึ้นเป็นพิเศษเมื่อแบบสอบถามใช้เวลา 20 วินาที มันทำงานได้ดีจากนั้นตัดสินใจไม่ทำงาน:

  • 2 วินาที
  • 1 วินาที
  • 30 วินาที
  • 3 วินาที
  • 2 วินาที

และไม่มีรายการอื่น ๆ ที่ยากเย็นแสนเข็ญที่ฉันสามารถหาได้ ไม่ใช่ระหว่างการสำรองข้อมูลบันทึกธุรกรรมทุก 2 ชั่วโมง

สิ่งที่คนอื่นอาจจะเป็น?

มีอะไรที่ฉันสามารถพูดได้นอกเหนือจาก: "เซิร์ฟเวอร์"หรือไม่?

แก้ไข : สัมพันธ์ตามเวลาของวัน

ฉันรู้ว่าฉันมีความสัมพันธ์กับระยะเวลาทุกอย่าง:

  • ตรรกะอ่าน
  • อ่านทางกายภาพ
  • การใช้ซีพียู

แต่สิ่งหนึ่งที่ฉันไม่ได้มีความสัมพันธ์มันจะเป็นช่วงเวลาของวัน บางทีการสำรองข้อมูลบันทึกธุรกรรมทุก 2 ชั่วโมงอาจเป็นปัญหา

หรือบางทีอาจจะชะลอตัวไม่เกิดขึ้นในระหว่างการ chucks ด่าน?

Nope:

ป้อนคำอธิบายรูปภาพที่นี่

Intel Xeon Gold Quad-core 6142

แก้ไข - ผู้คนกำลังตั้งสมมติฐานแผนการดำเนินการแบบสอบถาม

ผู้คนกำลังตั้งสมมติฐานว่าแผนการดำเนินการแบบสอบถามจะต้องแตกต่างกันระหว่าง "เร็ว" และ "ช้า" พวกเขาจะไม่.

และเราสามารถเห็นสิ่งนี้ได้ทันทีจากการตรวจสอบ

เรารู้ว่าระยะเวลาคำถามที่นานขึ้นนั้นไม่ใช่เพราะแผนการดำเนินการ "ไม่ดี":

  • หนึ่งที่อ่านตรรกะมากขึ้น
  • อันที่ใช้ CPU มากขึ้นจากการรวมมากขึ้นและการค้นหาคีย์

เพราะหากการเพิ่มขึ้นของการอ่านหรือการเพิ่มขึ้นของ CPU เป็นสาเหตุของระยะเวลาการสืบค้นที่เพิ่มขึ้นเราจะเห็นแล้วว่าข้างต้น ไม่มีความสัมพันธ์กัน

แต่ให้ลองเชื่อมโยงช่วงเวลากับตัวชี้วัดพื้นที่อ่าน CPU:

ป้อนคำอธิบายรูปภาพที่นี่

มีความสัมพันธ์น้อยลง - ซึ่งเป็นความขัดแย้ง


แก้ไข : อัปเดตแผนภาพกระจายเพื่อแก้ไขข้อบกพร่องในแปลงกระจาย Excel ที่มีค่าจำนวนมาก

ขั้นตอนถัดไป

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

EXEC sp_configure 'blocked process threshold', '5';
RECONFIGURE

มันจะไม่อธิบายหากเคียวรีถูกบล็อคเป็นเวลา4วินาที แต่บางทีทุกอย่างที่บล็อกข้อความค้นหาเป็นเวลา 5 วินาทีก็บล็อกบางอย่างเป็นเวลา 4 วินาที

แผนช้า

นี่คือแผนช้าของทั้งสองโพรซีเดอร์ที่เก็บไว้ซึ่งถูกเรียกใช้งาน:

  • `EXECUTE FindFrob @CustomerID = 7383, @StartDate = '20190725 04: 00: 00.000', @EndDate = '20190726 04: 00: 00.000'
  • `EXECUTE FindFrob @CustomerID = 7383, @StartDate = '20190725 04: 00: 00.000', @EndDate = '20190726 04: 00: 00.000'

โพรซีเดอร์ที่เก็บไว้แบบเดียวกันโดยมีพารามิเตอร์เดียวกันรันกลับไปด้านหลัง:

| Duration (us) | CPU time (us) | Logical reads | Physical reads | 
|---------------|---------------|---------------|----------------|
|    13,984,446 |        47,000 |         5,110 |            771 |
|     4,603,566 |        47,000 |         5,126 |            740 |

โทร 1:

|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
    |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
    |    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
    |    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
    |    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
    |    |    |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
    |    |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]),  WHERE:([Contos
    |--Filter(WHERE:([Expr1009]>(1)))
     |--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
          |--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
           |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC

โทร 2

|--Nested Loops(Left Semi Join, OUTER REFERENCES:([Contoso2].[dbo].[Frobs].[FrobGUID]) OPTIMIZED)
    |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]))
    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([Contoso2].[dbo].[FrobTransactions].[RowNumber]) OPTIMIZED)
    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
    |    |    |    |--Nested Loops(Inner Join, OUTER REFERENCES:([tpi].[TransactionGUID]) OPTIMIZED)
    |    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[TransactionPatronInfo].[IX_TransactionPatronInfo_CustomerID_TransactionGUID] AS [tpi]), SEEK:([tpi].[CustomerID]=[@CustomerID]) ORDERED FORWARD)
    |    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[Transactions].[IX_Transactions_TransactionGUIDTransactionDate]), SEEK:([Contoso2].[dbo].[Transactions].[TransactionGUID]=[Contoso2].[dbo
    |    |    |    |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions2_MoneyAppearsOncePerTransaction]), SEEK:([Contoso2].[dbo].[FrobTransactions].[TransactionGUID]=[Contos
    |    |    |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactions_RowNumber]), SEEK:([Contoso2].[dbo].[FrobTransactions].[RowNumber]=[Contoso2].[dbo].[Fin
    |    |--Clustered Index Seek(OBJECT:([Contoso2].[dbo].[Frobs].[PK_Frobs_FrobGUID]), SEEK:([Contoso2].[dbo].[Frobs].[FrobGUID]=[Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]),  WHERE:([Contos
    |--Filter(WHERE:([Expr1009]>(1)))
     |--Compute Scalar(DEFINE:([Expr1009]=CONVERT_IMPLICIT(int,[Expr1012],0)))
          |--Stream Aggregate(DEFINE:([Expr1012]=Count(*)))
           |--Index Seek(OBJECT:([Contoso2].[dbo].[FrobTransactions].[IX_FrobTransactins_OnFrobGUID]), SEEK:([Contoso2].[dbo].[FrobTransactions].[OnFrobGUID]=[Contoso2].[dbo].[Frobs].[LC

มันสมเหตุสมผลสำหรับแผนการที่จะเหมือนกัน มันกำลังดำเนินการขั้นตอนการจัดเก็บเดียวกันกับพารามิเตอร์เดียวกัน


2
คุณสามารถโพสต์แผนคิวรีได้ - ดีหรือไม่ดี
Kin Shah

4
การเดาครั้งแรกของฉันจากที่นี่จะเป็นการปิดกั้น ...
Tibor Karaszi

3
ใครลงคะแนนในเรื่องนี้? มันเป็นคำถามที่ได้รับการวิจัยอย่างถี่ถ้วนและละเอียดถี่ถ้วนแม้ว่ามันจะขาดแผนการสืบค้น! +1 จากฉัน!
Vérace

4
คุณสรุปได้อย่างไรว่าแผนการสืบค้นเป็น "เหมือนกัน" คุณหมายถึงพวกเขามีรูปร่างเหมือนกันหรือไม่? โพสต์ไว้ที่อื่นเพื่อให้เราสามารถเปรียบเทียบได้เช่นกัน เพียงแค่บอกเราว่าพวกเขาเหมือนกันไม่ได้หมายความว่าพวกเขาเหมือนกัน
Aaron Bertrand

3
การเพิ่มแผนการดำเนินการแบบเฉียบพลันโดยใช้PasteThePlanสามารถทำให้เรามีความคิดว่าแบบสอบถามกำลังรออะไรอยู่
Randi Vertongen

คำตอบ:


2

ดูที่ wait_stats และมันจะแสดงให้เห็นว่าคอขวดที่ใหญ่ที่สุดบน SQL server ของคุณคืออะไร

ฉันเพิ่งประสบปัญหาที่แอปพลิเคชันภายนอกช้าเป็นระยะ ๆ การเรียกใช้กระบวนงานที่เก็บไว้บนเซิร์ฟเวอร์นั้นรวดเร็วเสมอแม้ว่า

การตรวจสอบประสิทธิภาพแสดงให้เห็นว่าไม่มีอะไรที่จะต้องกังวลเกี่ยวกับการใช้แคช SQL หรือการใช้ RAM และ IO บนเซิร์ฟเวอร์

สิ่งที่ช่วย จำกัด การสอบสวนให้แคบลงคือการสอบถามสถานะการรอที่ SQL รวบรวม sys.dm_os_wait_stats

สคริปต์ที่ยอดเยี่ยมในเว็บไซต์ SQLSkillsจะแสดงสคริปต์ที่คุณพบมากที่สุด จากนั้นคุณสามารถ จำกัด การค้นหาเพื่อระบุสาเหตุ

เมื่อคุณรู้ว่าการรอคอยเป็นปัญหาใหญ่อะไรสคริปต์นี้จะช่วยให้แคบลงว่าเซสชัน / ฐานข้อมูลใดกำลังประสบกับการรอ:

SELECT OSW.session_id,
       OSW.wait_duration_ms,
       OSW.wait_type,
       DB_NAME(EXR.database_id) AS DatabaseName
FROM sys.dm_os_waiting_tasks OSW
INNER JOIN sys.dm_exec_sessions EXS ON OSW.session_id = EXS.session_id
INNER JOIN sys.dm_exec_requests EXR ON EXR.session_id = OSW.session_id
OPTION(Recompile);

แบบสอบถามดังกล่าวและรายละเอียดเพิ่มเติมได้จากเว็บไซต์ MSSQLTips

sp_BlitzFirstสคริปต์จาก Brent Ozar ของเว็บไซต์นอกจากนี้ยังจะแสดงให้คุณเห็นสิ่งที่ก่อให้เกิดการชะลอตัว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.