تكوين SQL Server و PerfMon Friends

في الصورة ، هناك مشهد من الكوميديا ​​القديمة الجيدة "طائرة" - يتذكره من يرتدونها.



إنها ليست هنا بالصدفة. لكن مفيد لاحقًا.

Dba لا تحب perfmon


ليس الأمر على الإطلاق لأن واجهة PerfMon لم تتغير مع Windows NT 3.1 (؟) وتعيد دفء ألفي. بالمناسبة ، ربما شخص يعرف تفسير هذه الحقيقة الغريبة. تتم إعادة كتابة لوحة التحكم عدة مرات في السنة. حتى الآلة الحاسبة أعيدت كتابتها. لكن ليس الكمال.

يعتقد DBA مع كلمات الغلاف. عندما يصل طبيب DBA جيد إلى خادم SQL مريض ، يفتح حقيبته ، وفي الحقيبة هناك عدد كبير من الأحياء التي تخدمه بإخلاص. يأخذ أقصر منهم من الذاكرة. في بعض الأحيان ، يمكن أن تنظر DBA في مقاييس PerfMon - القرص الفعلي أو طول قائمة انتظار القرص. ومع ذلك ، سيحصل DBA الحقيقي على مقاييس خادم SQL الخاصة به ، ليس من خلال PerfMon ، ولكن مع التصحيح ، على سبيل المثال ، مثل:

select * from sys.dm_os_performance_counters 
  where object_name='SQLServer:Buffer Manager' 
    and counter_name like 'Page life expectancy%' 
	and instance_name=''

عندما يسأله ممثلو تكنولوجيا المعلومات ، المطلقون من مجال DBA ، "ما المقاييس التي تريد منا أن نجمعها؟" (حسنًا ، هناك كل أنواع الأشكال المتقطعة والمربعة ، وما إلى ذلك) ، ثم يبدأ DBA في التفكير في النصوص البرمجية ، والباقي حول مقاييس الأداء في الوقت نفسه ، كقاعدة ، يحاولون التخلص من جميع المقاييس على DBA. عندما يحدث هذا ، تكون الصورة عديمة الفائدة في ازدحامها. ثم سيساعدني مقطع فيديو قصير من فيلم "طائرة" .

نتيجة لذلك ، يكتب DBA keri ، الذي يكتب إحصائيات كل N دقيقة إلى لوحة ما في قاعدة بيانات DBAtasks. هل تعرف نفسك؟

المحامي الشيطان (بيرمون)


ومع ذلك ، تعد عدادات الأداء أداة قياسية. يمكن تسجيلها ، وتعيين التنبيهات ، ولكن الأهم من ذلك ، هناك عدد كبير من الأنظمة التي "تدمج" هذه المقاييس من العديد من الأجهزة في مستودع مركزي ، وتسمح لك بتحليلها وإنشاء مخططات جميلة (وليس مثل perfmon).

اتضح أنه يمكننا تكوين صداقات مع عالم SQL وعالم PerfMon!

أدناه سأوضح كيف.

الآن سوف تذهب التفاصيل


كمثال ، سنعرض كيفية تصدير المقاييس التي لا تنشرها SQL نفسها إلى PerfMon. على سبيل المثال ، الاستعلام أدناه:

select
  convert(numeric(10,2),round(((sum(version_store_reserved_page_count)*1.0)/128.00),2)),
  convert(numeric(10,2),round(((sum(user_object_reserved_page_count)*1.0)/128.00),2)),
  convert(numeric(10,2),round(((sum(internal_object_reserved_page_count)*1.0)/128.00),2))
from
  tempdb.sys.dm_db_file_space_usage;

إرجاع مقدار مساحة tempdb المستخدمة من قبل مخزن الإصدار (للقطات) وكائنات المستخدم (علامة التبويب # وعلامة التبويب ##) ومساحة التخزين المؤقت / الفرز. دعنا ننشئ مقاييس لهم (18+ ، والفرق غير موثقة)

dbcc addinstance ('SQLServer:User Settable', 'TempDB version store KB')
dbcc addinstance ('SQLServer:User Settable', 'TempDB user store KB')
dbcc addinstance ('SQLServer:User Settable', 'TempDB sort store KB')

سيؤدي هذا إلى إنشاء ثلاثة مقاييس في SQLServer -> UserSettable -> Query. المقاييس هي أعداد صحيحة - int (وليس bigint). بالإضافة إلى ذلك ، يتم تفسير معناها كما هو. أي إذا كنت بحاجة إلى دلتا من القيمة السابقة ، فهذا هو قلقك. ولكن في هذه الحالة ، نحتاج فقط إلى تعيين قيم للمقاييس:

declare @TEMPDBver int, @TEMPDBuser int, @TEMPDBsort int
select

@TEMPDBver = convert(numeric(10,2),round(((sum(version_store_reserved_page_count) *1.0)/128.00),2)),
@TEMPDBuser = convert(numeric(10,2),round(((sum(user_object_reserved_page_count) *1.0)/128.00),2)),
@TEMPDBsort = convert(numeric(10,2),round(((sum(internal_object_reserved_page_count) *1.0)/128.00),2))
from tempdb.sys.dm_db_file_space_usage;

if @TEMPDBver is not null    
  dbcc setinstance ('SQLServer:User Settable', 'Query', 
    'TempDB version store KB', @TEMPDBver)
if @TEMPDBuser is not null   
  dbcc setinstance ('SQLServer:User Settable', 'Query', 
   'TempDB user store KB', @TEMPDBuser)
if @TEMPDBsort is not null   
  dbcc setinstance ('SQLServer:User Settable', 'Query', 
    'TempDB sort store KB', @TEMPDBsort)

في الواقع ، هذا كل شيء. الآن فقط اتصل بهذا الرمز بانتظام وسيعمل كل شيء.

عدادات دلتا


الآن دعونا نجري عداد دلتا. سيكون هذا هو مهلة القفل بالميلي ثانية.

dbcc addinstance ('SQLServer:User Settable', 'LOCK ms per s')

هنا يمكنك الاعتراض على وجود مثل هذا المقياس بالفعل:

select * from sys.dm_os_performance_counters 
  where counter_name like 'Lock Wait Time (ms)%' 
    and instance_name='_Total'
    and object_name='SQLServer:Locks'

لكن هذا المقياس متسق في النهاية فقط. كما تتذكر ، إذا كانت البروتونات غير مستقرة ، فإن أي قاعدة بيانات في الكون تكون في النهاية متسقة. أي إذا قمت بإنشاء قفل ونظرت إلى قيمة هذا المقياس ، فلن ينمو! وفقط في نهاية القفل ، ستقفز قيمته بشكل حاد طوال فترة الانتظار الكاملة. على الرسم البياني ، بدلاً من "الهضبة" المتوقعة ، ستحصل على ذروة حادة ، والتي تفسد أيضًا

مقياسك على طول المحور Y. نفس المشكلة مع kvery:

select sum(wait_time_ms) 
  from sys.dm_os_wait_stats 
  where wait_type like 'LCK_%'

لذلك ، يجب أن نضيف وقت الوقت الحالي إلى وقت الأقفال "المكتملة":

declare @NEWlock bigint
select @NEWlock=sum(wait_time_ms) 
  from sys.dm_os_wait_stats 
  where wait_type like 'LCK_%' -- finished waits
select @NEWlock=@NEWlock+isnull(sum(waittime),0) 
  from master.dbo.sysprocesses 
  where blocked>0 and lastwaittype like 'LCK_%' -- waits in progress

يعطي هذا السؤال بالفعل الهضبة الصحيحة على الرسم البياني.

الآن نحن بحاجة إلى النظر في دلتا من القيمة السابقة. هناك طريقتان:

  • قم بتصميم عملية كمهمة يتم استدعاؤها بشكل متكرر (لنقل مرة واحدة في الدقيقة). إنشاء تسمية لتخزين القيم السابقة. في الواقع ، غالبًا ما يكون من السيئ الاتصال بالوظيفة (النفقات العامة + المنافسة على تاريخ تنفيذ الوظائف) ، ويمكنك الاستغناء عن لوحة إضافية:
  • قم بإنشاء عملية يتم تشغيلها في حلقة لا نهائية باستخدام waitfor. تتذكر العملية القيمة السابقة في المتغير. سنقوم بمعالجة العملية كوظيفة بجدولين: عند بدء التشغيل ومرة ​​كل ساعة (في حالة سقوط الوظيفة ، سيتم إعادة تشغيلها)

في الحالة الثانية ، من الممكن القيام بدورة كل خمس ثوانٍ أو حتى أكثر. لذا نحصل على:

declare @OLDlock bigint, @NEWlock bigint
declare @lock int, @seconds int = 5 -- must match WAITFOR
loop:
  set @OLDlock=@NEWlock -- shift new to old
  select @NEWlock=sum(wait_time_ms) 
    from sys.dm_os_wait_stats 
	where wait_type like 'LCK_%' -- finished waits
  select @NEWlock=@NEWlock+isnull(sum(waittime),0) 
    from master.dbo.sysprocesses 
	where blocked>0 and lastwaittype like 'LCK_%' -- waits in progress
  set @lock=(@NEWlock-@OLDlock)/@seconds -- this is delta
  if @lock is not null    
    dbcc setinstance ('SQLServer:User Settable', 'Query', 
	  'LOCK ms per s', @lock)
  waitfor delay '00:00:05' 
goto loop

يرجى ملاحظة أنه في المرة الأولى التي تقوم فيها بتشغيل حلقة DBCC ، سيتم تخطيها (وهو صحيح) ، لأنOLDlock (و قفل) ستكون فارغة.

All Articles