ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

ืฉื•ื‘ ื”ืžืฉืš ื ื•ืฉื ื”ืกื™ื“ื•ืจ Zero Touch PROD ืชื—ืช RDS. DBAs ืขืชื™ื“ื™ื™ื ืœื ื™ื•ื›ืœื• ืœื”ืชื—ื‘ืจ ืœืฉืจืชื™ PROD ื™ืฉื™ืจื•ืช, ืืš ื™ื•ื›ืœื• ืœื”ืฉืชืžืฉ ื’'ื ืงื™ื ืก ืžืฉืจื•ืช ืœืงื‘ื•ืฆื” ืžืฆื•ืžืฆืžืช ืฉืœ ืคืขื•ืœื•ืช. ื”-DBA ืžืฉื™ืง ืืช ื”ืขื‘ื•ื“ื” ื•ืœืื—ืจ ื–ืžืŸ ืžื” ืžืงื‘ืœ ืžื›ืชื‘ ืขื ื“ื™ื•ื•ื— ืขืœ ืกื™ื•ื ื”ืคืขื•ืœื”. ื”ื‘ื” ื ื‘ื—ืŸ ื“ืจื›ื™ื ืœื”ืฆื™ื’ ืชื•ืฆืื•ืช ืืœื• ืœืžืฉืชืžืฉ.

ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

ื˜ืงืกื˜ ืจื’ื™ืœ

ื ืชื—ื™ืœ ืขื ื”ื˜ืจื™ื•ื•ื™ืืœื™ ื‘ื™ื•ืชืจ. ื”ืฉื™ื˜ื” ื”ืจืืฉื•ื ื” ื›ืœ ื›ืš ืคืฉื•ื˜ื” ืฉืื™ืŸ ื‘ืืžืช ืขืœ ืžื” ืœื“ื‘ืจ (ื”ืžื—ื‘ืจ ืžืฉืชืžืฉ ืœื”ืœืŸ ื‘ืขื‘ื•ื“ื•ืช FreeStyle):

ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

sqlcmd ืขื•ืฉื” ืžืฉื”ื• ื•ืื ื—ื ื• ืžืฆื™ื’ื™ื ืื•ืชื• ืœืžืฉืชืžืฉ. ืื™ื“ื™ืืœื™ ืขื‘ื•ืจ, ืœืžืฉืœ, ืขื‘ื•ื“ื•ืช ื’ื™ื‘ื•ื™:

ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

ืืœ ืชืฉื›ื—, ืื’ื‘, ืฉืชื—ืช RDS ื’ื™ื‘ื•ื™/ืฉื—ื–ื•ืจ ื”ื•ื ืืกื™ื ื›ืจื•ื ื™, ืื– ืืชื” ืฆืจื™ืš ืœื—ื›ื•ืช ืœื–ื”:

declare @rds table
  (id int, task_type varchar(128), database_name sysname, pct int, duration int, 
   lifecycle varchar(128), taskinfo varchar(max) null, 
   upd datetime, cre datetime,
   s3 varchar(256), ovr int, KMS varchar(256) null)
waitfor delay '00:00:20' 
insert into @rds exec msdb.dbo.rds_task_status @db_name='{db}'
select @xid=max(id) from @rds

again:
waitfor delay '00:00:02'
delete from @rds
insert into @rds exec msdb.dbo.rds_task_status @db_name='{db}' 
# {db} substituted with db name by powershell
select @stat=lifecycle,@info=taskinfo from @rds where id=@xid
if @stat not in ('ERROR','SUCCESS','CANCELLED') goto again

ืฉื™ื˜ื” ืฉื ื™ื™ื”, CSV

ื”ื›ืœ ื›ืืŸ ื’ื ืžืื•ื“ ืคืฉื•ื˜:

ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

ืขื ื–ืืช, ืฉื™ื˜ื” ื–ื• ืคื•ืขืœืช ืจืง ืื ื”ื ืชื•ื ื™ื ื”ืžื•ื—ื–ืจื™ื ื‘-CSV ื”ื "ืคืฉื•ื˜ื™ื". ืื ืชื ืกื” ืœื”ื—ื–ื™ืจ, ืœืžืฉืœ, ืจืฉื™ืžื” ืฉืœ ืฉืื™ืœืชื•ืช ืื™ื ื˜ื ืกื™ื‘ื™ื•ืช ืฉืœ TOP N CPU ื‘ื“ืจืš ื–ื•, ื”-CSV "ื™ื—ืœื™ื“" ื‘ื’ืœืœ ื”ืขื•ื‘ื“ื” ืฉื˜ืงืกื˜ ื”ืฉืื™ืœืชื” ื™ื›ื•ืœ ืœื”ื›ื™ืœ ื›ืœ ืชื•ื•ื™ื - ืคืกื™ืงื™ื, ืžืจื›ืื•ืช ื•ืืคื™ืœื• ืžืขื‘ืจื™ ืฉื•ืจื”. ืœื›ืŸ, ืื ื—ื ื• ืฆืจื™ื›ื™ื ืžืฉื”ื• ื™ื•ืชืจ ืžืกื•ื‘ืš.

ืฉืœื˜ื™ื ื™ืคื™ื ื‘-HTML

ืื ื™ ืืชืŸ ืœืš ืžื™ื“ ืงื˜ืข ืงื•ื“

$Header = @"
<style>
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
</style>
"@
  
$Result = invoke-Sqlcmd -ConnectionString $jstr -Query "select * from DbInv" `
  | Select-Object -Property * -ExcludeProperty "ItemArray", "RowError", "RowState", "Table", "HasErrors"
if ($Result -eq $null) { $cnt = 0; }
elseif ($Result.getType().FullName -eq "System.Management.Automation.PSCustomObject") { $cnt = 1; }
else { $cnt = $Result.Rows.Count; } 
if ($cnt -gt 0) {
  $body = "<h2>My table</h2>"
  $Result | ConvertTo-HTML -Title "Rows" -Head $header -body $body `
    | Out-File "res.log" -Append -Encoding UTF8
  } else {
    "<h3>No data</h3>" | Out-File "res.log" -Append -Encoding UTF8
  }

ืื’ื‘, ืฉื™ืžื• ืœื‘ ืœืงื• ืขื System.Management.Automation.PSCustomObject, ื–ื” ืงืกื•ื, ืื ื™ืฉ ื‘ื“ื™ื•ืง ืฉื•ืจื” ืื—ืช ื‘ืจืฉืช ืื– ื ื•ืฆืจื• ื›ืžื” ื‘ืขื™ื•ืช. ื”ืคืชืจื•ืŸ ื ืœืงื— ืžื”ืื™ื ื˜ืจื ื˜ ื‘ืœื™ ื”ืจื‘ื” ื”ื‘ื ื”. ื›ืชื•ืฆืื” ืžื›ืš, ืชืงื‘ืœ ืคืœื˜ ื‘ืคื•ืจืžื˜ ื›ื–ื”:

ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

ืฆื™ื•ืจ ื’ืจืคื™ื

ืื–ื”ืจื”: ืงื•ื“ ืงื™ื ืงื™ ืœืžื˜ื”!
ื™ืฉ ืฉืื™ืœืชื” ืžืฆื—ื™ืงื” ื‘ืฉืจืช SQL ืฉืžืฆื™ื’ื” ืืช ื”ืžืขื‘ื“ ื‘-N ื”ื“ืงื•ืช ื”ืื—ืจื•ื ื•ืช - ืžืกืชื‘ืจ ืฉื”ื—ื‘ืจ ืจืก"ืŸ ื–ื•ื›ืจ ื”ื›ืœ! ื ืกื” ืืช ื”ื—ื™ื“ื•ืŸ ื”ื–ื”:

DECLARE @ts_now bigint = (SELECT cpu_ticks/(cpu_ticks/ms_ticks) 
  FROM sys.dm_os_sys_info WITH (NOLOCK)); 
SELECT TOP(256) 
  DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) AS [EventTime],
  SQLProcessUtilization AS [SQLCPU], 
  100 - SystemIdle - SQLProcessUtilization AS [OtherCPU]
FROM (SELECT record.value('(./Record/@id)[1]', 'int') AS record_id, 
  record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') 
    AS [SystemIdle], 
  record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') 
    AS [SQLProcessUtilization], [timestamp] 
  FROM (SELECT [timestamp], CONVERT(xml, record) AS [record] 
  FROM sys.dm_os_ring_buffers WITH (NOLOCK)
  WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' 
    AND record LIKE N'%<SystemHealth>%') AS x) AS y 
ORDER BY 1 DESC OPTION (RECOMPILE);

ื›ืขืช, ื‘ืืžืฆืขื•ืช ื”ืขื™ืฆื•ื‘ ื”ื–ื” (ืžืฉืชื ื” $Fragment)

<table style="width: 100%"><tbody><tr style="background-color: white; height: 2pt;">
  <td style="width: SQLCPU%; background-color: green;"></td>
  <td style="width: OtherCPU%; background-color: blue;"></td>
  <td style="width: REST%; background-color: #C0C0C0;"></td></tr></tbody>
</table>

ืื ื• ื™ื›ื•ืœื™ื ืœื™ืฆื•ืจ ืืช ื’ื•ืฃ ื”ืžื›ืชื‘:

$Result = invoke-Sqlcmd -ConnectionString $connstr -Query $Query `
  | Select-Object -Property * -ExcludeProperty `
  "ItemArray", "RowError", "RowState", "Table", "HasErrors"
if ($Result.HasRows) {
  foreach($item in $Result) 
    { 
    $time = $itemEventTime 
    $sqlcpu = $item.SQLCPU
    $other = $itemOtherCPU
    $rest = 100 - $sqlcpu - $other
    $f = $fragment -replace "SQLCPU", $sqlcpu
    $f = $f -replace "OtherCPU", $other
    $f = $f -replace "REST", $rest
    $f | Out-File "res.log" -Append -Encoding UTF8
    }

ืžื” ืฉื™ืจืื” ื›ืš:

ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

ื›ืŸ, ืžืกื™ื™ื” ื™ื•ื“ืข ื”ืจื‘ื” ืขืœ ืกื˜ื™ื•ืช! ืžืขื ื™ื™ืŸ ืฉื”ืงื•ื“ ื”ื–ื” ืžื›ื™ืœ: Powershell (ื›ืชื•ื‘ ื‘ื•), SQL, Xquery, HTML. ื—ื‘ืœ ืฉืื ื—ื ื• ืœื ื™ื›ื•ืœื™ื ืœื”ื•ืกื™ืฃ Javascript ืœ-HTML (ืžื›ื™ื•ื•ืŸ ืฉื–ื” ืžื™ื•ืขื“ ืœื›ืชื™ื‘ื”), ืื‘ืœ ืœื™ื˜ื•ืฉ ืงื•ื“ Python (ืฉืืคืฉืจ ืœื”ืฉืชืžืฉ ื‘ื• ื‘-SQL) ื”ื•ื ื—ื•ื‘ืชื• ืฉืœ ื›ื•ืœื!

ืคืœื˜ ืžืขืงื‘ ืฉืœ SQL profiler

ื‘ืจื•ืจ ืฉื”ืขืงื™ื‘ื” ืœื ืชืชืื™ื ืœ-CSV ื‘ื’ืœืœ ื”ืฉื“ื” TextData. ืื‘ืœ ื”ืฆื’ืช ืจืฉืช ืขืงื‘ื•ืช ื‘ืžื›ืชื‘ ื”ื™ื ื’ื ืžื•ื–ืจื” - ื”ืŸ ื‘ื’ืœืœ ื”ื’ื•ื“ืœ ื•ื”ืŸ ื‘ื’ืœืœ ืฉื”ื ืชื•ื ื™ื ื”ืืœื” ืžืฉืžืฉื™ื ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืœื ื™ืชื•ื— ื ื•ืกืฃ. ืœื›ืŸ, ืื ื• ืขื•ืฉื™ื ืืช ื”ืคืขื•ืœื•ืช ื”ื‘ืื•ืช: ืื ื• ืžืชืงืฉืจื™ื ื“ืจืš invoke-SqlCmd ืชืกืจื™ื˜ ืžืกื•ื™ื, ืฉื‘ืขื•ืžืงื• ื”ื•ื ื ืขืฉื”

select 
  SPID,EventClass,TextData,
  Duration,Reads,Writes,CPU,
  StartTime,EndTime,DatabaseName,HostName,
  ApplicationName,LoginName
   from ::fn_trace_gettable ( @filename , default )  

ื”ื‘ื ื‘ืชื•ืจ ะดั€ัƒะณะพะผ ื‘ืฉืจืช ื”ื ื’ื™ืฉ ืขืœ ื™ื“ื™ ื”-DBA, ืงื™ื™ื ืžืกื“ ื ืชื•ื ื™ื Traces ืขื ืชื‘ื ื™ืช ืจื™ืงื”, ื”- Model plate, ืžื•ื›ืŸ ืœืงื‘ืœ ืืช ื›ืœ ื”ืขืžื•ื“ื•ืช ืฉืฆื•ื™ื ื•. ืื ื• ืžืขืชื™ืงื™ื ืžื•ื“ืœ ื–ื” ืœื˜ื‘ืœื” ื—ื“ืฉื” ืขื ืฉื ื™ื™ื—ื•ื“ื™:

$dt = Get-Date -format "yyyyMMdd"
$tm = Get-Date -format "hhmmss"
$tableName = $srv + "_" + $dt + "_" + $tm
$copytab = "select * into " + $tableName + " from Model"
invoke-SqlCmd -ConnectionString $tstr -Query $copytab 

ื•ืขื›ืฉื™ื• ืื ื—ื ื• ื™ื›ื•ืœื™ื ืœื›ืชื•ื‘ ืืช ืขืงื‘ื•ืชื™ื ื• ืœืชื•ื›ื• ื‘ืืžืฆืขื•ืช Data.SqlClient.SqlBulkCopy - ื›ื‘ืจ ื ืชืชื™ ื“ื•ื’ืžื” ืœื›ืš ืœืขื™ืœ. ื›ืŸ, ื–ื” ื™ื”ื™ื” ื ื—ืžื“ ื’ื ืœื”ืกื•ื•ืช ืงื‘ื•ืขื™ื ื‘-TextData:

# mask data
foreach ($Row in $Result)
{ 
  $v = $Row["TextData"]
  $v = $v -replace "'([^']{2,})'", "'str'" -replace "[0-9][0-9]+", '999'
  $Row["TextData"] = $v
}

ืื ื• ืžื—ืœื™ืคื™ื ืžืกืคืจื™ื ื‘ืื•ืจืš ืฉืœ ื™ื•ืชืจ ืžืชื• ืื—ื“ ื‘-999, ื•ืžื—ืœื™ืคื™ื ืžื—ืจื•ื–ื•ืช ืืจื•ื›ื•ืช ืžืชื• ืื—ื“ ื‘-'str'. ืžืกืคืจื™ื ืž-0 ืขื“ 9 ืžืฉืžืฉื™ื ืœืขืชื™ื ืงืจื•ื‘ื•ืช ื›ื“ื’ืœื™ื, ื•ืื ื—ื ื• ืœื ื ื•ื’ืขื™ื ื‘ื”ื, ื›ืžื• ื’ื ืžื—ืจื•ื–ื•ืช ืจื™ืงื•ืช ื•ืชื•ื•ื™ื ื‘ื•ื“ื“ื™ื - 'Y', 'N' ื•ื›ื•' ื ืžืฆืื•ืช ื‘ื™ื ื™ื”ื ืœืขืชื™ื ืงืจื•ื‘ื•ืช.

ื‘ื•ืื• ื ื•ืกื™ืฃ ืงืฆืช ืฆื‘ืข ืœื—ื™ื™ื ื• (ืœืคื—ื•ืช 18+)

ื‘ื˜ื‘ืœืื•ืช, ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืืชื” ืจื•ืฆื” ืœื”ื“ื’ื™ืฉ ืชืื™ื ื”ื“ื•ืจืฉื™ื ืชืฉื•ืžืช ืœื‘. ืœืžืฉืœ, FAILS, ืจืžืช ืคื™ืฆื•ืœ ื’ื‘ื•ื”ื” ื•ื›ื•'. ื›ืžื•ื‘ืŸ ืฉื ื™ืชืŸ ืœืขืฉื•ืช ื–ืืช ื‘-SQL ื—ืฉื•ืฃ, ืœื™ื™ืฆืจ HTML ื‘ืืžืฆืขื•ืช PRINT, ื•ืœื”ื’ื“ื™ืจ ืืช ืกื•ื’ ื”ืงื•ื‘ืฅ ืœ-HTML ื‘ื’'ื ืงื™ื ืก:

declare @body varchar(max), @chunk varchar(max)
set @body='<font face="Lucida Console" size="3">'
set @body=@body+'<b>Server name: '+@@servername+'</b><br>'
set @body=@body+'<br><br>'
set @body=@body+'<table><tr><th>Job</th><th>Last Run</th><th>Avg Duration, sec</th><th>Last Run, Sec</th><th>Last Status</th></tr>'
print @body

DECLARE tab CURSOR FOR SELECT '<tr><td>'+name+'</td><td>'+
  LastRun+'</td><td>'+
  convert(varchar,AvgDuration)+'</td><td>'+
  convert(varchar,LastDuration)+'</td><td>'+
    case when LastStatus<>'Succeeded' then '<font color="red">' else '' end+
      LastStatus+
      case when LastStatus<>'Succeeded' then '</font>' else '' end+
     +'</td><td>'
  from #j2
OPEN tab;  
FETCH NEXT FROM tab into @chunk
WHILE @@FETCH_STATUS = 0  
BEGIN
  print @chunk
  FETCH NEXT FROM tab into @chunk;  
END  
CLOSE tab;  
DEALLOCATE tab;
print '</table>'

ืœืžื” ื›ืชื‘ืชื™ ืงื•ื“ ื›ื–ื”?

ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

ืื‘ืœ ื™ืฉ ืคืชืจื•ืŸ ื™ืคื” ื™ื•ืชืจ. ื”ืžืจ ืœ-HTML ืœื ื ื•ืชืŸ ืœื ื• ืœืฆื‘ื•ืข ืืช ื”ืชืื™ื, ืื‘ืœ ืื ื—ื ื• ื™ื›ื•ืœื™ื ืœืขืฉื•ืช ืืช ื–ื” ืœืื—ืจ ืžืขืฉื”. ืœื“ื•ื’ืžื”, ืื ื• ืจื•ืฆื™ื ืœื‘ื—ื•ืจ ืชืื™ื ืขื ืจืžืช ืคื™ืฆื•ืœ ืฉืœ ื™ื•ืชืจ ืž-80 ื•ื™ื•ืชืจ ืž-90. ื‘ื•ืื• ื ื•ืกื™ืฃ ืกื’ื ื•ื ื•ืช:

<style>
.SQLmarkup-red { color: red; background-color: yellow; }
.SQLmarkup-yellow { color: black; background-color: #FFFFE0; }
.SQLmarkup-default { color: black; background-color: white; }
</style>

ื‘ืฉืื™ืœืชื” ืขืฆืžื” ื ื•ืกื™ืฃ ืขืžื•ื“ืช ื“ืžื” ืžื™ื“ ืœืคื ื™ ืขืžื•ื“ื” ืฉืื ื• ืจื•ืฆื™ื ืœืฆื‘ื•ืข. ื™ืฉ ืœืงืจื•ื ืœืขืžื•ื“ื” SQLmarkup-ืžืฉื”ื•:

case  
  when ps.avg_fragmentation_in_percent>=90.0 then 'SQLmarkup-red'
  when ps.avg_fragmentation_in_percent>=80.0 then 'SQLmarkup-yellow'
  else 'SQLmarkup-default' 
  end as [SQLmarkup-1], 
ps.avg_fragmentation_in_percent, 

ื›ืขืช, ืœืื—ืจ ืฉืงื™ื‘ืœื ื• ืืช ื”-HTML ืฉื ื•ืฆืจ ืขืœ ื™ื“ื™ Powershell, ื ืกื™ืจ ืืช ืขืžื•ื“ืช ื”ื“ืžื” ืžื”ื›ื•ืชืจืช, ื•ื‘ื’ื•ืฃ ื”ื ืชื•ื ื™ื ื ืขื‘ื™ืจ ืืช ื”ืขืจืš ืžื”ืขืžื•ื“ื” ืœืกื’ื ื•ืŸ. ื–ื” ื ืขืฉื” ืขื ืฉื ื™ ื”ื—ืœืคื•ืช ื‘ืœื‘ื“:

$html = $html `
  -replace "<th>SQLmarkup[^<]*</th>", "" `
  -replace "<td>SQLmarkup-(.+?)</td><td>",'<td class="SQLmarkup-$1">'

ืชื•ืฆืื”:
ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

ื–ื” ืœื ืืœื’ื ื˜ื™? ืœืžืจื•ืช ืฉืœื, ื”ืฆื‘ื™ืขื” ื”ื–ื• ืžื–ื›ื™ืจื” ืœื™ ืžืฉื”ื•
ืื•ื˜ื•ืžืฆื™ื” ืฉืœ ืฉืจืช SQL ื‘ื’'ื ืงื™ื ืก: ื”ื—ื–ืจืช ื”ืชื•ืฆืื” ื™ืคื”

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”