{"id":515,"date":"2018-01-17T14:46:25","date_gmt":"2018-01-17T14:46:25","guid":{"rendered":"https:\/\/sqldoubleg.live-website.com\/?p=515"},"modified":"2018-01-17T14:50:39","modified_gmt":"2018-01-17T14:50:39","slug":"getting-perfmon-data-into-sql-server-part-iii","status":"publish","type":"post","link":"https:\/\/www.sqldoubleg.com\/es\/2018\/01\/17\/getting-perfmon-data-into-sql-server-part-iii\/","title":{"rendered":"Insertando datos de rendimiento en SQL Server, Parte III"},"content":{"rendered":"<p>En este post muestro como desplegar de foma sencilla la soluci\u00f3n propuesta anteriormente para insertar datos de redimiento en SQL Server a m\u00faltiples servidores con m\u00faltiples instancias de SQL Server&nbsp;Realmente no ten\u00eda pensado escribir este post, despu\u00e9s de escribir la <a href=\"https:\/\/sqldoubleg.live-website.com\/es\/2017\/12\/20\/getting-perfmon-data-into-sql-server\/\">Parte I<\/a> y la <a href=\"https:\/\/sqldoubleg.live-website.com\/es\/2017\/12\/27\/getting-perfmon-data-into-sql-server-part-ii\/\">Parte II<\/a>, cre\u00eda que ya estaba bien as\u00ed, pero cuando lleg\u00f3 a hora de desplegar la soluci\u00f3n a los diferentes servidores SQL Server que necesito monitorizar, me di cuenta que necesitaba algo m\u00e1s para automatizar el proceso y no tener que ir a cada servidor haciendo click por las diferentes ventanas que puede ser bastante aburrido, verdad?<\/p>\n<p>&nbsp;<br \/>\n<strong>Antecedentes<\/strong><\/p>\n<p>Como he dicho, a la hora de desplegar la solucion propuesta en mis anteriores posts en multiples servidores, esta puede resultar bastante tediosa, especialmente si tenemos diferentes instancias de SQL Server corriendo en la misma m\u00e1quina, ya que el nombre de los contadores depende del nombre de la instancia, con lo cu\u00e1l habr\u00eda que seleccionar manualmente todos esos contadores y no ser\u00eda suficiente con tener una sola plantilla para crear el recopilador de datos.<\/p>\n<p>As\u00ed que decid\u00ed hacer lo que m\u00e1s me gusta y me puse a escribir unas consultas que combinadas con un poco de powershell har\u00e1n el trabajo.<\/p>\n<p>La l\u00f3gica es f\u00e1cil, tenemos tres tablas donde vamos a almacenar los diferentes servidores SQL Server donde queremos crear los recopiladores de datos (en formato Servidor\\Instancia), luego tenemos otras dos tablas, una para los contadores de Windows y otra para los contadores de SQL Server.<\/p>\n<p>Para obtener la lista completa de contadores, pod\u00e9is ejecutar el siguiente comando.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\ntypeperf -q &gt; c:\\temp\\all_server_counters.txt\r\n<\/pre>\n<p>&nbsp;<br \/>\nEsto crear\u00e1 un archivo con la lista completa de contadores, es necesario ejecutarla en un servidor SQL Server con la instancia por defecto instalada para obtener tambi\u00e9n los contadores de SQL Server.<\/p>\n<p>Luego debeis revisar la lista y elegir los contadores en los que est\u00e1is m\u00e1s interesados.<\/p>\n<p>La consulta generar\u00e1 solamente <strong>una fila por m\u00e1quina<\/strong> pero esta contendr\u00e1 <strong>todos los contadores de Windows m\u00e1s los contadores SQL Server para cada instancia<\/strong>, as\u00ed tendremos la foto completa en un solo fichero de salida y podremos correlacionar los datos mas f\u00e1cilmente.<\/p>\n<p>Despu\u00e9s de eso, utilizo Logman para crear de forma remota los diferentes recopiladores de datos en cada servidor, as\u00ed que aseg\u00faraos de tener suficientes privilegios administrativos para realizar la tarea.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nImport-Module sqlps -DisableNameChecking\r\n \r\n$cmssrv = &quot;localhost\\MSSQL2016&quot;;\r\n$templatePath = &quot;c:\\temp\\templates\\&quot;; \r\n$outputPath = &quot;c:\\Perfmon\\&quot;\r\n \r\n$serverlist = invoke-sqlcmd -ServerInstance $cmssrv -Database &quot;master&quot; -query &quot;\r\nIF OBJECT_ID('tempdb..#SQLServers')         IS NOT NULL DROP TABLE #SQLServers\r\nIF OBJECT_ID('tempdb..#ServerCounters')     IS NOT NULL DROP TABLE #ServerCounters\r\nIF OBJECT_ID('tempdb..#SQLServerCounters')  IS NOT NULL DROP TABLE #SQLServerCounters\r\n \r\nCREATE TABLE #SQLServers        (ID INT NOT NULL IDENTITY, instance_name SYSNAME)\r\nCREATE TABLE #ServerCounters    (ID INT NOT NULL IDENTITY, counter_name SYSNAME)\r\nCREATE TABLE #SQLServerCounters (ID INT NOT NULL IDENTITY, counter_name SYSNAME)\r\n \r\nINSERT INTO #SQLServers\r\nVALUES ('localhost')\r\n, ('localhost\\MSSQL2014')\r\n, ('localhost\\MSSQL2016')\r\n, ('localhost\\MSSQL2017')\r\n \r\nINSERT INTO #ServerCounters ( counter_name )\r\nVALUES ('\\Memory\\Available MBytes')\r\n, ('\\NUMA Node Memory(*)\\Available MBytes')\r\n, ('\\Paging File(*)\\% Usage')\r\n, ('\\PhysicalDisk(*)\\Avg. Disk Queue Length')\r\n, ('\\PhysicalDisk(*)\\Current Disk Queue Length')\r\n, ('\\PhysicalDisk(*)\\Disk Reads\/sec')\r\n, ('\\PhysicalDisk(*)\\Disk Writes\/sec')\r\n, ('\\PhysicalDisk(*)\\Avg. Disk sec\/Read')\r\n, ('\\PhysicalDisk(*)\\Avg. Disk sec\/Write')\r\n, ('\\PhysicalDisk(*)\\Avg. Disk Read Queue Length')\r\n, ('\\PhysicalDisk(*)\\Avg. Disk Write Queue Length')\r\n, ('\\System\\Processor Queue Length')\r\n, ('\\Processor(*)\\% Processor Time')\r\n, ('\\Network Interface(*)\\Bytes Total\/sec')\r\n, ('\\Network Interface(*)\\Packets\/sec')\r\n, ('\\Network Interface(*)\\Packets Received\/sec')\r\n, ('\\Network Interface(*)\\Packets Sent\/sec')\r\n \r\nINSERT INTO #SQLServerCounters ( counter_name )\r\nVALUES ('\\SQLServer:Buffer Manager\\Page life expectancy')\r\n, ('\\SQLServer:Buffer Node(*)\\Page life expectancy')\r\n, ('\\SQLServer:General Statistics\\User Connections')\r\n, ('\\SQLServer:Memory Manager\\Memory Grants Pending')\r\n, ('\\SQLServer:SQL Statistics\\Batch Requests\/sec')\r\n, ('\\SQLServer:SQL Statistics\\SQL Compilations\/sec')\r\n, ('\\SQLServer:SQL Statistics\\SQL Re-Compilations\/sec')\r\n \r\nSELECT DISTINCT \r\n        CASE \r\n            WHEN CHARINDEX('\\', s.instance_name) &gt; 0 \r\n                THEN LEFT(s.instance_name, CHARINDEX('\\', s.instance_name) - 1) \r\n            ELSE s.instance_name \r\n        END AS server_name\r\n        , STUFF((SELECT CHAR(10) + counter_name FROM #ServerCounters AS c ORDER BY ID FOR XML PATH('')), 1,1,'') \r\n        + \r\n        (SELECT CHAR(10) + \r\n                    CASE WHEN CHARINDEX('\\', s1.instance_name) = 0  \r\n                        THEN c.counter_name \r\n                        ELSE REPLACE(c.counter_name, 'SQLServer', 'MSSQL$' + CONVERT(SYSNAME, RIGHT(s1.instance_name, LEN(s1.instance_name) - CHARINDEX('\\', s1.instance_name))))\r\n                    END\r\n             FROM #SQLServerCounters AS c \r\n             CROSS APPLY #SQLServers AS s1\r\n             ORDER BY s1.instance_name, c.ID \r\n             FOR XML PATH('')\r\n        ) AS template\r\n    FROM #SQLServers AS s\r\n    ORDER BY server_name&quot;\r\n \r\nforeach ($servername in $serverlist) {\r\n     \r\n    $OutputExists = Get-Item -Path $templatePath -ErrorAction SilentlyContinue;\r\n \r\n    if ($OutputExists -eq $null) {\r\n        Write-Output &quot;Creating directory $templatePath&quot;;\r\n        New-Item -Path $templatePath -Type Directory;\r\n    }\r\n \r\n    $templateFile = &quot;$($templatePath)\\$($servername.server_name)_DBA_collector.txt&quot;;\r\n    $servername.template | Out-File -FilePath $templateFile;\r\n    $serverOutputPath = &quot;$($outputPath)$($servername.server_name)&quot;;\r\n \r\n    $OutputExists = Get-Item -Path $serverOutputPath -ErrorAction SilentlyContinue;\r\n \r\n    if ($OutputExists -eq $null) {\r\n        Write-Output &quot;Creating directory $serverOutputPath&quot;;\r\n        New-Item -Path $serverOutputPath -Type Directory;\r\n    }\r\n     \r\n    try{\r\n        Write-Output &quot;Trying to create counter in $($servername.server_name)&quot;;\r\n        logman create counter -s $servername.server_name -cf $templateFile -n &quot;DBA_perfmonCollector&quot; -f &quot;csv&quot; -si 15 -o &quot;$($serverOutputPath)\\$($servername.server_name)&quot; -a -cnf &quot;24:00:00&quot; -v &quot;nnnnnn&quot;;\r\n        logman start -s $servername.server_name -n &quot;DBA_perfmonCollector&quot;;\r\n    }\r\n    catch{\r\n        Write-Output &quot;Failed to create counter in $($servername.server_name)&quot;;\r\n    }\r\n}\r\n<\/pre>\n<p>&nbsp;<br \/>\nDespu\u00e9s de ejecutar con \u00e9xito este script de powershell, tendremos los distintos recopiladores de datos creados en cada servidor.<\/p>\n<p>Yo recomendar\u00eda utilizar una carpeta compartida para centralizar todos los ficheros de salida en una misma ubicaci\u00f3n y evitar que el disco c:\\ se llene, cosa que puede ser un verdadero dolor de muelas.<\/p>\n<p>&nbsp;<br \/>\n<strong>Conclusi\u00f3n <\/strong><\/p>\n<p>Como ya he dicho antes, no me esperaba escribir esta publicaci\u00f3n, pero sent\u00ed como que faltaba algo con solo las dos publicaciones anteriores.<\/p>\n<p>Actualmente estoy trabajando en algunos informes para hacer que los datos sean un poco m\u00e1s \u00fatiles, porque la cantidad de informaci\u00f3n puede ser enorme y realmente puede frustrar el prop\u00f3sito de tenerla.<\/p>\n<p>Espero que os hay gustado y estad atentos!<\/p>\n<p>\u00a1Gracias!<br \/>\n&nbsp;<br \/>\n<\/p>","protected":false},"excerpt":{"rendered":"<p>En este post muestro como desplegar de foma sencilla la soluci\u00f3n propuesta anteriormente para insertar datos de redimiento en SQL Server a m\u00faltiples servidores con m\u00faltiples instancias de SQL Server&nbsp;Realmente no ten\u00eda&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,19],"tags":[82,58,83,84],"_links":{"self":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts\/515"}],"collection":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/comments?post=515"}],"version-history":[{"count":0,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/posts\/515\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/media?parent=515"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/categories?post=515"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqldoubleg.com\/es\/wp-json\/wp\/v2\/tags?post=515"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}