{"id":969,"date":"2017-08-09T15:16:46","date_gmt":"2017-08-09T15:16:46","guid":{"rendered":"https:\/\/www.tiagoneves.net\/blog\/?p=969"},"modified":"2017-08-09T19:04:46","modified_gmt":"2017-08-09T19:04:46","slug":"retornando-consultas-em-execucao","status":"publish","type":"post","link":"https:\/\/www.tiagoneves.net\/blog\/retornando-consultas-em-execucao\/","title":{"rendered":"Retornando consultas em execu\u00e7\u00e3o"},"content":{"rendered":"<p style=\"text-align: justify;\">Ol\u00e1 pessoal, tudo certo?<\/p>\n<p style=\"text-align: justify;\">No post de hoje vou compartilhar um script que retorna as informa\u00e7\u00f5es de consumo de CPU, disco, mem\u00f3ria entre outras informa\u00e7\u00f5es. Esse script foi desenvolvido junto com o <a href=\"https:\/\/www.dirceuresende.com\/blog\" target=\"_blank\" rel=\"noopener\">Dirceu Resende<\/a>, para quem j\u00e1 conhece a famosa <a href=\"http:\/\/whoisactive.com\/\" target=\"_blank\" rel=\"noopener\">sp_WhoIsActive<\/a> desenvolvida pelo <a href=\"http:\/\/sqlblog.com\/blogs\/adam_machanic\/\" target=\"_blank\" rel=\"noopener\">Adam Machanic<\/a>, vai perceber que elas tem praticamente o mesmo retorno.<\/p>\n<p style=\"text-align: justify;\">Por diversas vezes, j\u00e1 tivemos problemas de lentid\u00e3o ao executar a sp_WhoIsActive em ambientes com press\u00e3o de processamento, disco e conten\u00e7\u00e3o no TempDB, fazendo com que o retorno da SP demorasse v\u00e1rios segundos, at\u00e9 mesmo alguns minutos, <strong>uma vez que a sp_WhoIsActive tem muita utiliza\u00e7\u00e3o de TempDB para retornar os resultados da forma que ela retorna atualmente, que em um momento de crise torne invi\u00e1vel utiliza-la.<\/strong><\/p>\n<p style=\"text-align: justify;\">Com o objetivo de prover uma solu\u00e7\u00e3o parecida, e que fosse mais leve e retorna-se as informa\u00e7\u00f5es necess\u00e1rias para a realiza\u00e7\u00e3o de um troubleshooting, permitindo que ela seja executada rapidamente mesmo em cen\u00e1rios como o citado acima, criamos essa vers\u00e3o mais \u201cenxuta\u201d, retornado as principais informa\u00e7\u00f5es e sem utilizar os diversos par\u00e2metros que a sp_WhoIsActive original nos fornece.<\/p>\n<p>A sp_WhoIsActive \u00e9 muito mais completa, pois dependendo dos par\u00e2metros que s\u00e3o passados na sua execu\u00e7\u00e3o ela retorna v\u00e1rias outras informa\u00e7\u00f5es que n\u00e3o est\u00e3o contempladas no script abaixo. Se voc\u00ea quiser conhecer mais a sp_WhoIsActive a documenta\u00e7\u00e3o est\u00e1 dispon\u00edvel no site <a href=\"http:\/\/whoisactive.com\/docs\/\" target=\"_blank\" rel=\"noopener\">http:\/\/whoisactive.com\/docs\/<\/a>.<\/p>\n<p style=\"text-align: justify;\"><strong>Principais diferen\u00e7as da sp_WhoIsActive<\/strong><\/p>\n<ul>\n<li style=\"text-align: justify;\">N\u00e3o utiliza a TempDB;<\/li>\n<li style=\"text-align: justify;\">Execu\u00e7\u00e3o mais r\u00e1pida;<\/li>\n<li style=\"text-align: justify;\">C\u00f3digo mais simples de entender;<\/li>\n<li style=\"text-align: justify;\">Pode ser facilmente utilizada como view, table-valued function ou scalar function, permitindo utilizar order by, select into, where, etc;<\/li>\n<li style=\"text-align: justify;\">Al\u00e9m de mostrar a query em execu\u00e7\u00e3o, mostra tamb\u00e9m o Outer Command (a sp_WhoIsActive tamb\u00e9m mostra se utilizado o par\u00e2metro @get_outer_command = 1);<\/li>\n<li style=\"text-align: justify;\">Caso a sess\u00e3o seja de um job, mostra o nome do job na coluna program_name;<\/li>\n<li style=\"text-align: justify;\">Retorna o XML do plano de execu\u00e7\u00e3o (a sp_WhoIsActive tamb\u00e9m mostra se utilizado o par\u00e2metro @get_plans = 1).<\/li>\n<\/ul>\n<pre class=\"theme:ssms2012 lang:tsql decode:true\">SELECT\r\n    RIGHT('00' + CAST(DATEDIFF(SECOND, COALESCE(B.start_time, A.login_time), GETDATE()) \/ 86400 AS VARCHAR), 2) + ' ' + \r\n    RIGHT('00' + CAST((DATEDIFF(SECOND, COALESCE(B.start_time, A.login_time), GETDATE()) \/ 3600) % 24 AS VARCHAR), 2) + ':' + \r\n    RIGHT('00' + CAST((DATEDIFF(SECOND, COALESCE(B.start_time, A.login_time), GETDATE()) \/ 60) % 60 AS VARCHAR), 2) + ':' + \r\n    RIGHT('00' + CAST(DATEDIFF(SECOND, COALESCE(B.start_time, A.login_time), GETDATE()) % 60 AS VARCHAR), 2) + '.' + \r\n    RIGHT('000' + CAST(DATEDIFF(SECOND, COALESCE(B.start_time, A.login_time), GETDATE()) AS VARCHAR), 3) \r\n    AS Duration,\r\n    A.session_id AS session_id,\r\n    B.command,\r\n    TRY_CAST('&lt;?query --' + CHAR(10) + (\r\n        SELECT TOP 1 SUBSTRING(X.[text], B.statement_start_offset \/ 2 + 1, ((CASE\r\n                                                                          WHEN B.statement_end_offset = -1 THEN (LEN(CONVERT(NVARCHAR(MAX), X.[text])) * 2)\r\n                                                                          ELSE B.statement_end_offset\r\n                                                                      END\r\n                                                                     ) - B.statement_start_offset\r\n                                                                    ) \/ 2 + 1\r\n                     )\r\n    ) + CHAR(10) + '--?&gt;' AS XML) AS sql_text,\r\n    TRY_CAST('&lt;?query --' + CHAR(10) + X.[text] + CHAR(10) + '--?&gt;' AS XML) AS sql_command,\r\n    A.login_name,\r\n    '(' + CAST(COALESCE(E.wait_duration_ms, B.wait_time) AS VARCHAR(20)) + 'ms)' + COALESCE(E.wait_type, B.wait_type) + COALESCE((CASE \r\n        WHEN COALESCE(E.wait_type, B.wait_type) LIKE 'PAGEIOLATCH%' THEN ':' + DB_NAME(LEFT(E.resource_description, CHARINDEX(':', E.resource_description) - 1)) + ':' + SUBSTRING(E.resource_description, CHARINDEX(':', E.resource_description) + 1, 999)\r\n        WHEN COALESCE(E.wait_type, B.wait_type) = 'OLEDB' THEN '[' + REPLACE(REPLACE(E.resource_description, ' (SPID=', ':'), ')', '') + ']'\r\n        ELSE ''\r\n    END), '') AS wait_info,\r\n    FORMAT(COALESCE(B.cpu_time, 0), '###,###,###,###,###,###,###,##0') AS CPU,\r\n    FORMAT(COALESCE(F.tempdb_allocations, 0), '###,###,###,###,###,###,###,##0') AS tempdb_allocations,\r\n    FORMAT(COALESCE((CASE WHEN F.tempdb_allocations &gt; F.tempdb_current THEN F.tempdb_allocations - F.tempdb_current ELSE 0 END), 0), '###,###,###,###,###,###,###,##0') AS tempdb_current,\r\n    FORMAT(COALESCE(B.logical_reads, 0), '###,###,###,###,###,###,###,##0') AS reads,\r\n    FORMAT(COALESCE(B.writes, 0), '###,###,###,###,###,###,###,##0') AS writes,\r\n    FORMAT(COALESCE(B.reads, 0), '###,###,###,###,###,###,###,##0') AS physical_reads,\r\n    FORMAT(COALESCE(B.granted_query_memory, 0), '###,###,###,###,###,###,###,##0') AS used_memory,\r\n    NULLIF(B.blocking_session_id, 0) AS blocking_session_id,\r\n    COALESCE(G.blocked_session_count, 0) AS blocked_session_count,\r\n    (CASE \r\n        WHEN B.[deadlock_priority] &lt;= -5 THEN 'Low'\r\n        WHEN B.[deadlock_priority] &gt; -5 AND B.[deadlock_priority] &lt; 5 AND B.[deadlock_priority] &lt; 5 THEN 'Normal'\r\n        WHEN B.[deadlock_priority] &gt;= 5 THEN 'High'\r\n    END) + ' (' + CAST(B.[deadlock_priority] AS VARCHAR(3)) + ')' AS [deadlock_priority],\r\n    B.row_count,\r\n    COALESCE(A.open_transaction_count, 0) AS open_tran_count,\r\n    (CASE B.transaction_isolation_level\r\n        WHEN 0 THEN 'Unspecified' \r\n        WHEN 1 THEN 'ReadUncommitted' \r\n        WHEN 2 THEN 'ReadCommitted' \r\n        WHEN 3 THEN 'Repeatable' \r\n        WHEN 4 THEN 'Serializable' \r\n        WHEN 5 THEN 'Snapshot'\r\n    END) AS transaction_isolation_level,\r\n    A.[status],\r\n    NULLIF(B.percent_complete, 0) AS percent_complete,\r\n    A.[host_name],\r\n    COALESCE(DB_NAME(CAST(B.database_id AS VARCHAR)), 'master') AS [database_name],\r\n    (CASE WHEN D.name IS NOT NULL THEN 'SQLAgent - TSQL Job (' + D.[name] + ' - ' + SUBSTRING(A.[program_name], 67, LEN(A.[program_name]) - 67) +  ')' ELSE A.[program_name] END) AS [program_name],\r\n    COALESCE(B.start_time, A.last_request_end_time) AS start_time,\r\n    A.login_time,\r\n    COALESCE(B.request_id, 0) AS request_id,\r\n    W.query_plan\r\nFROM\r\n    sys.dm_exec_sessions AS A WITH (NOLOCK)\r\n    LEFT JOIN sys.dm_exec_requests AS B WITH (NOLOCK) ON A.session_id = B.session_id\r\n    JOIN sys.dm_exec_connections AS C WITH (NOLOCK) ON A.session_id = C.session_id AND A.endpoint_id = C.endpoint_id\r\n    LEFT JOIN msdb.dbo.sysjobs AS D ON RIGHT(D.job_id, 10) = RIGHT(SUBSTRING(A.[program_name], 30, 34), 10)\r\n    LEFT JOIN (\r\n        SELECT\r\n            session_id, \r\n            wait_type,\r\n\t\t\twait_duration_ms,\r\n            resource_description,\r\n\t\t\tROW_NUMBER() OVER(PARTITION BY session_id ORDER BY (CASE WHEN wait_type LIKE 'PAGEIO%' THEN 0 ELSE 1 END), wait_duration_ms DESC) AS Ranking\r\n        FROM \r\n            sys.dm_os_waiting_tasks\r\n    ) E ON A.session_id = E.session_id AND E.Ranking = 1\r\n    LEFT JOIN (\r\n        SELECT\r\n            session_id,\r\n            request_id,\r\n            SUM(internal_objects_alloc_page_count + user_objects_alloc_page_count) AS tempdb_allocations,\r\n            SUM(internal_objects_dealloc_page_count + user_objects_dealloc_page_count) AS tempdb_current\r\n        FROM\r\n            sys.dm_db_task_space_usage\r\n        GROUP BY\r\n            session_id,\r\n            request_id\r\n    ) F ON B.session_id = F.session_id AND B.request_id = F.request_id\r\n    LEFT JOIN (\r\n        SELECT \r\n            blocking_session_id,\r\n            COUNT(*) AS blocked_session_count\r\n        FROM \r\n            sys.dm_exec_requests\r\n        WHERE \r\n            blocking_session_id != 0\r\n        GROUP BY\r\n            blocking_session_id\r\n    ) G ON A.session_id = G.blocking_session_id\r\n    OUTER APPLY sys.dm_exec_sql_text(COALESCE(B.[sql_handle], C.most_recent_sql_handle)) AS X\r\n    OUTER APPLY sys.dm_exec_query_plan(COALESCE(B.[sql_handle], C.most_recent_sql_handle)) AS W\r\nWHERE\r\n    A.session_id &gt; 50\r\n    AND A.session_id &lt;&gt; @@SPID\r\n    AND (A.[status] != 'sleeping' OR (A.[status] = 'sleeping' AND A.open_transaction_count &gt; 0))\r\n<\/pre>\n<p>Resultado da execu\u00e7\u00e3o da sp_Tiny_WhoisActive<\/p>\n<p><a href=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2017\/07\/Resultado_Tiny_WhoisActive.png?ssl=1\" rel=\"lightbox[969]\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-970\" src=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2017\/07\/Resultado_Tiny_WhoisActive.png?resize=678%2C52&#038;ssl=1\" alt=\"\" width=\"678\" height=\"52\" srcset=\"https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2017\/07\/Resultado_Tiny_WhoisActive.png?w=1262&amp;ssl=1 1262w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2017\/07\/Resultado_Tiny_WhoisActive.png?resize=300%2C23&amp;ssl=1 300w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2017\/07\/Resultado_Tiny_WhoisActive.png?resize=768%2C59&amp;ssl=1 768w, https:\/\/i0.wp.com\/www.tiagoneves.net\/blog\/wp-content\/uploads\/2017\/07\/Resultado_Tiny_WhoisActive.png?resize=1024%2C79&amp;ssl=1 1024w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/a><\/p>\n<p style=\"text-align: justify;\">Uma observa\u00e7\u00e3o \u00e9 que no script utilizamos a fun\u00e7\u00e3o <a href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/t-sql\/functions\/format-transact-sql\" target=\"_blank\" rel=\"noopener\">Format<\/a>, para formatar os contadores, ela est\u00e1 dispon\u00edvel somente a partir do <strong>SQL Server 2012<\/strong>, ent\u00e3o em vers\u00e3o anteriores voc\u00ea ter\u00e1 que remover a fun\u00e7\u00e3o.<\/p>\n<p style=\"text-align: justify;\">Caso queira contribuir no desenvolvimento, o c\u00f3digo fonte est\u00e1 dispon\u00edvel no <a href=\"https:\/\/github.com\/dirceuresende\/tiny-sp_whoisactive\" target=\"_blank\" rel=\"noopener\">GitHub <\/a>do Dirceu.<\/p>\n<p style=\"text-align: justify;\">Bom pessoal, por hoje \u00e9 isso.<\/p>\n<p style=\"text-align: justify;\">Um grande abra\u00e7o.<\/p>\n<p style=\"text-align: justify;\">Tiago Neves<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ol\u00e1 pessoal, tudo certo? No post de hoje vou compartilhar um script que retorna as informa\u00e7\u00f5es de consumo de CPU, disco, mem\u00f3ria entre outras informa\u00e7\u00f5es. Esse script foi desenvolvido junto com o Dirceu Resende, para quem j\u00e1 conhece a famosa sp_WhoIsActive desenvolvida pelo Adam Machanic, vai perceber que elas tem praticamente o mesmo retorno. Por [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rop_custom_images_group":[],"rop_custom_messages_group":[],"rop_publish_now":"initial","rop_publish_now_accounts":{"twitter_91251433_91251433":""},"rop_publish_now_history":[],"rop_publish_now_status":"pending","_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpscppro_dont_share_socialmedia":false,"_wpscppro_custom_social_share_image":0,"_facebook_share_type":"","_twitter_share_type":"","_linkedin_share_type":"","_pinterest_share_type":"","_linkedin_share_type_page":"","_instagram_share_type":"","_medium_share_type":"","_threads_share_type":"","_google_business_share_type":"","_selected_social_profile":[],"_wpsp_enable_custom_social_template":false,"_wpsp_social_scheduling":{"enabled":false,"datetime":null,"platforms":[],"status":"template_only","dateOption":"today","timeOption":"now","customDays":"","customHours":"","customDate":"","customTime":"","schedulingType":"absolute"},"_wpsp_active_default_template":true},"categories":[2,4,138,5],"tags":[197,196,35,105,198],"class_list":["post-969","post","type-post","status-publish","format-standard","hentry","category-casos-do-dia-a-dia","category-scripts","category-troubleshooting","category-virtual-pass-br","tag-script","tag-sp_whoisactive","tag-sql-server","tag-tempdb","tag-troubleshooting"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6eIyh-fD","jetpack-related-posts":[],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/posts\/969","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/comments?post=969"}],"version-history":[{"count":7,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/posts\/969\/revisions"}],"predecessor-version":[{"id":985,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/posts\/969\/revisions\/985"}],"wp:attachment":[{"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/media?parent=969"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/categories?post=969"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tiagoneves.net\/blog\/wp-json\/wp\/v2\/tags?post=969"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}