การใช้งาน CPU สูงบนเซิร์ฟเวอร์ SQL - คิวรีช้า [ปิด]


11

MS SQL Server ของเราใช้ซีพียูประมาณ 95%

หลังจากรีสตาร์ทเซิร์ฟเวอร์ (ฮาร์ดแวร์) หรือรีสตาร์ท SQL-Service การใช้งานจะเป็น 0% และจะเพิ่มขึ้นอย่างช้า ๆ ในระยะเวลา 1-3 วัน ขึ้นอยู่กับว่ามีการใช้งานเท่าใด

เมื่อเกิน 80% ทุกคำถามจะช้ามาก

เว็บไซต์ของเราจัดการกับข้อความค้นหาจำนวนมากดังนั้นบางรายการใช้เวลา 45-60 วินาที หลังจากรีสตาร์ท (การใช้งาน CPU น้อยกว่า 80%) จะใช้เวลา 11-20 วินาทีในการค้นหาเดียวกัน


ฉันจะแก้ไขสิ่งนี้ได้อย่างไร ฉันได้อ่านออนไลน์แล้วที่ affinity masks สามารถปรับการใช้งาน CPU แต่การตั้งค่า Affinity ถูกปิดใช้งาน ฉันไม่สามารถเปลี่ยนได้ เป็นเพราะฉันมีเพียง 1 โปรเซสเซอร์หรือไม่

มีเคล็ดลับมากมายเกี่ยวกับข้อความค้นหาด้วยตนเอง แต่เว็บไซต์และบริการของเราค่อนข้างใหญ่และมีการเปลี่ยนแปลงมากเกินไป

ส่วนใหญ่แล้วจะได้รับการปรับให้เหมาะสมแล้ว


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

ระบบนี้ใช้โดยทีมค้นหาและกู้ภัยหลายร้อยแห่งและถ้า SQL-Service รีสตาร์ทระหว่างการเตือนภัยระบบจะหยุดทำงานและบุคคลที่เรียกใช้ในระบบจะไม่ได้รับแจ้ง


ฉันค้นหาทั่วสถานที่ แต่ไม่พบสิ่งใดนอกจากเรื่อง "Affinity Mask" ซึ่งฉันไม่สามารถเปลี่ยนแปลงได้

จะต้องมีวิธีการล้างแคช CPU โดยไม่ต้องยกเลิกการสืบค้นปัจจุบัน ... ใช่ไหม?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB

ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
พอลไวท์ 9

คำตอบ:


7

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

DBCC FREEPROCCACHE

คุณสามารถตรวจสอบเพื่อดูว่าการตั้งค่า parametrization บังคับคืออะไรถ้าการล้างแคชทำงานโดย:

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

นี่อาจถูกตั้งค่าเป็น 0 ซึ่งเป็นค่าเริ่มต้น หากพวกเขาต้องการคุณสามารถตั้งค่าที่เป็นจริงโดยการทำ:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

สิ่งนี้ควรทำในสภาพแวดล้อมการพัฒนาก่อนและดูว่าสิ่งนี้ส่งผลเสียต่อฐานข้อมูลด้วยวิธีอื่นหรือไม่ สามารถเปลี่ยนกลับได้โดยใช้:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;

5
โปรดทราบว่าการเพิ่มแคชโพรซีเดอร์อาจทำให้ CPU เสียหายมากเนื่องจากการค้นหาทั้งหมดจะต้องคอมไพล์แผนการดำเนินการของตนใหม่
Aaron Bertrand

18

Affinity ไม่ "ปรับการใช้งาน CPU" (เช่นในกรณีของคุณทำให้ CPU ทำงานน้อยลง) ช่วยให้คุณสามารถปิด CPU ได้ (อาจทำให้สามารถใช้งานอินสแตนซ์อื่นบนเครื่องเดียวกันได้) หรือตั้งค่า CPU เป็น ช่วยเหลือด้วย I / O เท่านั้น แม้ว่าคุณจะมีซีพียูหลายตัว แต่คุณก็ไม่สามารถที่จะใช้ตัวเดิมเพื่อช่วยในการตั้งเป้าหมายและมันเป็นไปไม่ได้ที่เราจะเดาได้ในตอนท้ายเพราะเราไม่รู้ว่าอะไรเป็นแรงผลักดันให้การใช้ซีพียูของคุณสูง อาจเป็นเพราะการจัดทำดัชนีที่แย่มากการรวบรวมที่มากเกินไปความอุดมสมบูรณ์ของ UDF สเกลาร์ I / O ที่ฟาดฟันใครจะรู้? (และสาเหตุของ I / O อาจเป็นสาเหตุได้ว่าหากฐานข้อมูลของคุณมีขนาดใหญ่กว่า 3 GB หรือมากกว่านั้นจะต้องสลับข้อมูลเข้าและออกจากหน่วยความจำบัฟเฟอร์พูลอย่างต่อเนื่องและสิ่งนี้จะใช้เวลากับ CPU)

แคชของ CPU เป็นช่องกระต่ายที่คุณไม่จำเป็นต้องลงไปด้วย ฉันสงสัยว่าซีพียูของคุณกำลังพุ่ง 95% เนื่องจากมีปัญหากับแคช CPU ของคุณ

เพื่อช่วย จำกัด แหล่งที่มาของแรงกดดันของ CPU และสมมติว่าคุณกำลังใช้โพรซีเดอร์ที่เก็บไว้คุณสามารถดูแบบสอบถามการวินิจฉัยนี้จาก Glenn Berry ( ที่มาจากที่นี่ ) - ตรวจสอบให้แน่ใจว่าคุณรันในบริบทของฐานข้อมูลที่ถูกต้อง:

-- Top Cached SPs By Total Worker time (SQL Server 2012). 
-- Worker time relates to CPU cost  (Query 44) (SP Worker Time)

SELECT TOP (25) 
  p.name AS [SP Name], 
  qs.total_worker_time AS [TotalWorkerTime], 
  qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], 
  qs.execution_count, 
  ISNULL(qs.execution_count/DATEDIFF(Second, qs.cached_time, GETDATE()), 0) 
    AS [Calls/Second],
  qs.total_elapsed_time, 
  qs.total_elapsed_time/qs.execution_count AS [avg_elapsed_time], 
  qs.cached_time
FROM sys.procedures AS p WITH (NOLOCK)
INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (NOLOCK)
ON p.[object_id] = qs.[object_id]
WHERE qs.database_id = DB_ID()
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

-- This helps you find the most expensive cached stored procedures from a CPU perspective
-- You should look at this if you see signs of CPU pressure

หากคุณไม่ได้ใช้กระบวนงานที่เก็บไว้ตัวอย่างนี้จาก John Samson สามารถช่วยแยกข้อความค้นหาเฉพาะกิจ ( ที่มาจากที่นี่ ):

SELECT TOP (25)
    qs.sql_handle,
    qs.execution_count,
    qs.total_worker_time AS Total_CPU,
    total_CPU_inSeconds = --Converted from microseconds
    qs.total_worker_time/1000000,
    average_CPU_inSeconds = --Converted from microseconds
    (qs.total_worker_time/1000000) / qs.execution_count,
    qs.total_elapsed_time,
    total_elapsed_time_inSeconds = --Converted from microseconds
    qs.total_elapsed_time/1000000,
    st.text,
    qp.query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS apply sys.dm_exec_query_plan (qs.plan_handle) AS qp
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

นอกจากนี้คุณยังสามารถดูsp_WhoIsActiveของ Adam Machanic ซึ่งเป็นกระบวนงานที่เก็บไว้ซึ่งสามารถวิเคราะห์แบบสอบถามที่กำลังทำงานอยู่ทั้งหมดได้อย่างรวดเร็วและอนุญาตให้คุณเรียงลำดับตามที่คุณต้องการ (เช่นในกรณีของคุณ@sort_order = '[CPU] DESC')

สิ่งแรกที่ฉันจะทำโดยเฉพาะอย่างยิ่งถ้านี่เป็นภารกิจที่สำคัญสำหรับทีมค้นหาและกู้ภัย - คือซื้อฮาร์ดแวร์ที่ดีกว่า คุณควรมี CPU มากขึ้นและ RAM มากขึ้นเพื่อให้บริการแอปพลิเคชันของคุณ นอกจากนี้คุณยังต้องการความพร้อมใช้งานที่สูงขึ้น (เช่นการทำคลัสเตอร์การทำมิเรอร์หรือกลุ่มความพร้อมใช้งาน) ไม่มีเหตุผลที่การรีบูตเครื่องทางกายภาพควรทำให้แอปพลิเคชันของคุณออฟไลน์โดยสมบูรณ์ - เรามีวิธีแก้ไขปัญหาที่ดีกว่า และสุดท้ายฉันก็สันนิษฐานว่า "เซิร์ฟเวอร์" นี้มีดิสก์ไดรฟ์แบบ spinny เพียงตัวเดียวเท่านั้น ซึ่งหมายความว่า I / O ทั้งหมด - จากระบบปฏิบัติการจากไฟล์ข้อมูล SQL Server, ไฟล์บันทึก, tempdb และอื่น ๆ ทั้งหมดผ่านตัวควบคุมเดียวและแบ่งปันกิจกรรมการอ่าน / เขียนบนไดรฟ์เดียว รับดิสก์เพิ่ม รับ SSD หาก / ที่ไหนที่คุณสามารถทำได้ ใช้ RAID และพยายามกระจาย I / O ออกให้ได้มากที่สุด

อย่างที่ทุกคนกล่าวว่าการขว้างฮาร์ดแวร์ที่มีปัญหาไม่ได้เป็นเพียงส่วนหนึ่งของการแก้ไข คุณต้องแยกสิ่งที่ทำให้เกิดการใช้งาน CPU มากเกินไปจากนั้นโจมตีปัญหาเหล่านั้นไม่ว่าคุณจะใช้ฮาร์ดแวร์ชนิดใด

ดูคำถาม StackOverflow นี้สำหรับแนวคิดอื่น ๆ :

/programming/945063/how-do-i-find-out-what-is-hammering-my-sql-server


0

คำแนะนำต่อไปนี้คือ 'shot in the dark' เพราะฉันไม่เห็นรหัสจริง

อย่างแรกคือ SP อาจเปิดเคอร์เซอร์และเปิดทิ้งไว้ อ่านค่า Cursors โดยเฉพาะอย่างยิ่ง Close และ Deallocate บางคนอาจปิด แต่ไม่ได้ยกเลิกการจัดสรรเคอร์เซอร์ พฤติกรรมอาจเปลี่ยนไปเนื่องจากการอัปเกรด 2012 อาจถือว่าเคอร์เซอร์ที่เหลือแตกต่างจาก 2008 R2

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

คุณใช้ WinLink โดยบังเอิญหรือไม่? บางสิ่งเกี่ยวกับเรื่องนี้ฟังดูคุ้นเคย


-4

คุณควรมีกลไกการแคชเช่น memcached เพื่อปรับปรุงประสิทธิภาพ


แต่นี่จะไม่เปลี่ยนการใช้งาน CPU บน SQL-Server ใช่ไหม มันจะทำให้การสืบค้นเร็วขึ้นบนเว็บไซต์และอาจมีปัญหาเกิดขึ้นเมื่อมีการเปลี่ยนแปลงตารางในขณะที่คนอื่นใช้ผลลัพธ์ memcached จากตารางเดียวกันใช่ไหม
Levi Johansen

@Levi หากคุณแคชผลลัพธ์การสืบค้นบางแห่งในระดับกลางดังนั้นการสืบค้นจะไม่ไปถึงฐานข้อมูล (ยกเว้นเมื่อคุณต้องการรีเฟรชแคช)
Aaron Bertrand

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