{"id":294,"date":"2010-06-05T09:34:40","date_gmt":"2010-06-05T12:34:40","guid":{"rendered":"http:\/\/fabriciodba.wordpress.com\/2010\/06\/05\/passo-a-passo-para-encontrar-as-querys-mais-demoradas-do-banco-de-dados-parte-2"},"modified":"2016-09-11T18:23:48","modified_gmt":"2016-09-11T21:23:48","slug":"passo-a-passo-para-encontrar-as-querys-mais-demoradas-do-banco-de-dados-parte-2","status":"publish","type":"post","link":"https:\/\/fabriciolima.net\/blog\/2010\/06\/05\/passo-a-passo-para-encontrar-as-querys-mais-demoradas-do-banco-de-dados-parte-2\/","title":{"rendered":"Passo a passo para encontrar as querys mais demoradas do Banco de Dados &#8211; Parte 2"},"content":{"rendered":"<div id=\"msgcns!874FDFFD5EC76B2E!445\" class=\"bvMsg\">\n<p>Continuando o artigo<a title=\"passo-a-passo-para-encontrar-as-querys-mais-demoradas-do-banco-de-dados-parte-1\/\" href=\"https:\/\/www.fabriciolima.net\/blog\/2010\/06\/05\/passo-a-passo-para-encontrar-as-querys-mais-demoradas-do-banco-de-dados-parte-1\/\" target=\"_blank\"> Passo a passo para encontrar as querys mais demoradas do Banco de Dados &#8211; Parte 1<\/a>.<\/p>\n<p>Agora que o<em> trace<\/em> j\u00e1 foi testado e vimos que ele realmente funciona, criaremos um <em>job<\/em> para enviar o<em> trace<\/em> para a tabela <em>de log<\/em> e automatizar todo o processo.<\/p>\n<p>Voc\u00ea deve criar um <em>Job<\/em> no <em>Management Studio<\/em> com o nome \u201c<em>DBA &#8211; Trace Querys Demoradas\u201d<\/em> e esse<em> job<\/em> deve possuir 3 <em>steps<\/em>.<\/p>\n<p><strong><em>STEP<\/em> 1<\/strong> <strong>&#8211;<\/strong> No primeiro <em>Step<\/em> devemos parar o trace momentaneamente para enviar todo o seu resultado para a tabela de log. Nesse <em>step<\/em>, voc\u00ea deve selecionar a <em>database<\/em> em que vc criou a tabela que armazenar\u00e1 o <em>trace<\/em> e incluir a <em>query<\/em> abaixo no <em>step<\/em>.<\/p>\n<pre class=\"lang:tsql decode:true \">\r\nDECLARE @Trace_Id INT\r\n\r\nSELECT @Trace_Id = [TraceId]\r\nFROM fn_trace_getinfo(0)\r\nWHERE CAST([value] AS VARCHAR(50)) = 'C:\\Trace\\Querys_Demoradas.trc'\r\n\r\nEXEC [dbo].[sp_trace_setstatus]  @traceid = @Trace_Id,  @status = 0 -- Interrompe o rastreamento especificado.\r\n\r\nEXEC [dbo].[sp_trace_setstatus]  @traceid = @Trace_Id,  @status = 2 -- Fecha o rastreamento especificado e exclui sua defini\u00e7\u00e3o do servidor.\r\n\r\nINSERT INTO [dbo].[Traces] (\t[Textdata], [NTUserName], [HostName], [ApplicationName], [LoginName], [SPID], [Duration], [Starttime],\r\n\t\t\t\t\t\t\t\t[EndTime], [Reads], [writes], [CPU], [Servername], [DatabaseName], [rowcounts], [SessionLoginName] )\r\nSELECT\t[Textdata], [NTUserName], [HostName], [ApplicationName], [LoginName], [SPID], CAST([Duration] \/ 1000\/ 1000.00 AS NUMERIC(15, 2)) [Duration], [Starttime],\r\n\t\t[EndTime], [Reads], [writes], [CPU], [Servername], [DatabaseName], [rowcounts], [SessionLoginName]\r\nFROM :: fn_trace_gettable('C:\\Trace\\Querys_Demoradas.trc', default)\r\nWHERE [Duration] IS NOT NULL\r\nORDER BY [Starttime]\r\n<\/pre>\n<p>Segue abaixo a figura de como fica esse <em>step<\/em>:<\/p>\n<p><a rel=\"WLPP\"><img loading=\"lazy\" decoding=\"async\" style=\"display: block; float: none; margin-left: auto; margin-right: auto; border: 0;\" title=\"Step1_thumb1\" src=\"https:\/\/www.fabriciolima.net\/blog\/wp-content\/uploads\/2010\/10\/step1_thumb15b45d.jpg?w=300\" alt=\"Step1_thumb1\" width=\"355\" height=\"284\" border=\"0\" \/><\/a><\/p>\n<p><strong><em>STEP<\/em> 2 &#8211;<\/strong> Agora que os dados do <em>trace<\/em> j\u00e1 foram armazenados na tabela, deve-se excluir o arquivo de <em>trace<\/em> para que um novo seja criado. Isso pode ser realizado executando o comando \u201c<em><strong>del C:\\Trace\\Querys_Demoradas.trc \/Q<\/strong><\/em>\u201d como pode ser visto na figura abaixo:<\/p>\n<p><a rel=\"WLPP\"><img loading=\"lazy\" decoding=\"async\" style=\"display: block; float: none; margin-left: auto; margin-right: auto; border: 0;\" title=\"Step2_thumb1\" src=\"https:\/\/www.fabriciolima.net\/blog\/wp-content\/uploads\/2010\/10\/step2_thumb15b45d.jpg?w=300\" alt=\"Step2_thumb1\" width=\"354\" height=\"311\" border=\"0\" \/><\/a><\/p>\n<p><strong>STEP 3 &#8211;<\/strong> Esse passo deve apenas recriar o <em>trace<\/em>. Similar ao <em>step 1<\/em>, voc\u00ea deve selecionar a <em>database<\/em> em que vc criou a procedure e rodar a <em>query<\/em> abaixo:<\/p>\n<pre class=\"lang:default decode:true \">\r\nEXEC [dbo].[stpCreate_Trace]\r\n<\/pre>\n<p>No meu ambiente, esse <em>job<\/em> roda de hora em hora no meu principal servidor de produ\u00e7\u00e3o, mas isso depende da sua necessidade. Eu tamb\u00e9m excluo os registros com mais de 60 dias, para que a tabela de <em>log<\/em> n\u00e3o fique muito grande, ja que n\u00e3o analiso esses registros mais antigos.<\/p>\n<p>Agora que nosso procedimento ja est\u00e1 em produ\u00e7\u00e3o, \u00e9 possivel atacar as <em>querys<\/em> mais demoradas.<\/p>\n<p>No meu ambiente, identifico as <em>procedures<\/em> que mais retornam no<em> trace<\/em> e realizo um agrupamento, como feito abaixo, para facilitar minha visualiza\u00e7\u00e3o di\u00e1ria. Para um exemplo, vou criar mais uma <em>procedure<\/em> de teste e execut\u00e1-las algumas vezes.<\/p>\n<pre class=\"lang:tsql decode:true \">\r\nCREATE PROCEDURE [dbo].[dbo].[stpTeste_Trace2]\r\nAS\r\nBEGIN\r\n    WAITFOR DELAY '00:00:04'\r\nEND\r\nGO\r\nEXEC [dbo].[stpTeste_Trace1] -- Procedure ja criada\r\nGO\r\nEXEC [dbo].[stpTeste_Trace1]\r\nGO\r\nEXEC [dbo].[stpTeste_Trace2]\r\nGO\r\nEXEC [dbo].[stpTeste_Trace2]\r\nGO\r\nEXEC [dbo].[stpTeste_Trace2]\r\nGO\r\nEXEC [dbo].[stpTeste_Trace2]\r\nGO\r\n<\/pre>\n<p>Depois de executadas, rodarei o <em>Job<\/em> para importar o arquivo de<em> trace<\/em> para a tabela de <em>log<\/em>.<\/p>\n<pre class=\"lang:default decode:true \">\r\nEXEC [msdb]..[sp_start_job] @job_name = 'DBA - Trace Querys Demoradas'\r\n<\/pre>\n<p>Com a <em>query<\/em> abaixo, podemos visualizar os dados armazenados no <em>trace<\/em> agrupados por <em>procedure<\/em>.<\/p>\n<pre class=\"lang:default decode:true \">\r\nDECLARE @Dt_Inicial DATETIME, @Dt_Final DATETIME\r\n\r\nSELECT\t@Dt_Inicial = CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME), \r\n\t\t@Dt_Final = CAST(FLOOR(CAST(GETDATE()+1 AS FLOAT)) AS DATETIME)\r\n\r\nSELECT\tCASE    \r\n\t\t\tWHEN [TextData] LIKE '%stpTeste_Trace1%' THEN 'stpTeste_Trace1'\r\n\t\t\tWHEN [TextData] LIKE '%stpTeste_Trace2%' THEN 'stpTeste_Trace2'\r\n\t\t\tELSE 'Outros' \r\n\t\tEND [Nm_Objeto],\r\n\t\tCOUNT(*) [QTD], \r\n\t\tSUM([Duration]) [Total], \r\n\t\tAVG([Duration]) [Media], \r\n\t\tMIN([Duration]) [Menor], \r\n\t\tMAX([Duration]) [Maior],\r\n\t\tSUM([Reads]) [Reads], \r\n\t\tSUM([writes]) [Writes], \r\n\t\tSUM([cpu]) [CPU]\r\nFROM [dbo].[Traces] WITH(NOLOCK)\r\nWHERE [Starttime] >= @Dt_Inicial AND [Starttime] < @Dt_Final -- Periodo a ser analizado\r\nGROUP BY\tCASE    \r\n\t\t\t\tWHEN [TextData] LIKE '%stpTeste_Trace1%' THEN 'stpTeste_Trace1'\r\n\t\t\t\tWHEN [TextData] LIKE '%stpTeste_Trace2%' THEN 'stpTeste_Trace2'\r\n\t\t\t\tELSE 'Outros' \r\n\t\t\tEND\r\nORDER BY [Total] DESC\r\n<\/pre>\n<p>Essa <em>query<\/em> retorna o seguinte resultado:<\/p>\n<p><a rel=\"WLPP\"><img loading=\"lazy\" decoding=\"async\" style=\"display: block; float: none; margin-left: auto; margin-right: auto; border: 0;\" title=\"ResultadoQuerysAgrupadas_thumb1\" src=\"http:\/\/fabriciodba.files.wordpress.com\/2010\/06\/resultadoquerysagrupadas_thumb15b35d.jpg?w=300\" alt=\"ResultadoQuerysAgrupadas_thumb1\" width=\"341\" height=\"60\" border=\"0\" \/><\/a><\/p>\n<p>Onde <em>QTD<\/em> \u00e9 a quantidade de vezes que a procedure demorou mais de 3 segundos, <em>Total<\/em> \u00e9 o tempo total dessas execu\u00e7\u00f5es, <em>Media<\/em> \u00e9 o tempo m\u00e9dio dessas execu\u00e7\u00f5es, <em>Menor<\/em> e <em>Maior<\/em> s\u00e3o os menores e maiores tempos respectivamente, e <em>Reads<\/em>, <em>Writes<\/em> e <em>CPU<\/em> \u00e9 a soma dos recursos que as execu\u00e7\u00f5es dessas procedures gastaram.<\/p>\n<p>Para quem viu o primeiro artigo que escrevi <a title=\"criando-um-checklist-automatico-do-banco-de-dados\/\" href=\"https:\/\/www.fabriciolima.net\/blog\/2010\/03\/24\/criando-um-checklist-automatico-do-banco-de-dados\/\" target=\"_blank\">Criando um CheckList Autom\u00e1tico do Banco de Dados<\/a> , eu recebo essa informa\u00e7\u00e3o em minha planilha de <em>CheckList<\/em> di\u00e1rio com um filtro para pegar o <em>trace<\/em> de 08:00am as 18:00pm do dia anterior. Desta forma, analiso quais s\u00e3o as <em>procedures<\/em> que mais demoram no meu ambiente para melhor\u00e1-las.<\/p>\n<p>Como j\u00e1 disse anteriormente, tenho esse procedimento implantado no meu principal servidor de produ\u00e7\u00e3o e ele n\u00e3o consome muitos recursos do servidor. Logo vale apena implement\u00e1-lo levando em conta que a informa\u00e7\u00e3o que voc\u00ea tem \u00e9 muito valiosa. \u00c9 poss\u00edvel identificar por exemplo, a partir de qual hor\u00e1rio os procedimentos do seu ambiente come\u00e7aram a apresentar uma lentid\u00e3o ou que tem algu\u00e9m da sua equipe de desenvolvimento rodando alguma <em>query<\/em> pesada no seu servidor de produ\u00e7\u00e3o no meio do dia ou ainda que no momento que executam a<em> procedure<\/em> A, ela faz com que muitas outras<em> procedures<\/em> fiquem lentas. Dentre outros benef\u00edcios.<\/p>\n<p>Sugiro fortemente que quem n\u00e3o possui uma rotina parecida com essa, tente implement\u00e1-la assim que poss\u00edvel.<\/p>\n<p>&nbsp;<br \/>\n<b>Gostou dessa dica?<\/b><\/p>\n<p>Cadastre seu e-mail para receber novos Posts e curta minha <a href=\"https:\/\/www.facebook.com\/FabricioLimaSolucoesemBancodeDados\/\" target=\"_blank\">P\u00e1gina no Facebook<\/a> para receber Dicas de Leituras e Eventos sobre SQL Server.<\/p>\n<p>Aprenda a criar essa e outras rotinas para administrar melhor seu SQL Server no meu <a href=\"https:\/\/www.fabriciolima.net\/cursos-online\/treinamento-tarefas-do-dia-a-dia-de-um-dba-online\/\" target=\"_blank\">Treinamento de Tarefas do Dia a Dia de um DBA<\/a>.<\/p>\n<p>Abra\u00e7os,<\/p>\n<p>Fabr\u00edcio Lima<\/p>\n<p>MCITP \u2013 Database Administrator<\/p>\n<p>Consultor e Instrutor SQL Server<\/p>\n<p>Trabalha com SQL Server desde 2006\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Continuando o artigo Passo a passo para encontrar as querys mais demoradas do Banco de Dados &#8211; Parte 1. Agora que o trace j\u00e1 foi testado e vimos que ele realmente funciona, criaremos um job para enviar o trace para a tabela de log e automatizar todo o processo. Voc\u00ea deve criar um Job no [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[3,280],"tags":[18,23,26,65,63,48,66,31,64,49,33,50,34,35,67,40],"class_list":["post-294","post","type-post","status-publish","format-standard","hentry","category-administracao-de-bd","category-virtual-pass-br","tag-checklist","tag-dba","tag-excel","tag-lentidao","tag-performance","tag-planilha","tag-problema","tag-profile","tag-query-lenta","tag-sql","tag-sql-server","tag-sql-server-2005","tag-sql-server-2008","tag-sql-server-2008-r2","tag-sql-server-passo-a-passo","tag-tuning"],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/posts\/294","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/comments?post=294"}],"version-history":[{"count":0,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/posts\/294\/revisions"}],"wp:attachment":[{"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/media?parent=294"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/categories?post=294"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/tags?post=294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}