Está en la página 1de 7

Power Bi - Analizar Instrucciones del Sql

Server
En los manejadores de bases de datos se pueden capturar estadísticas respecto al uso de sus recursos, entre
ellos estadísticas de ejecución de las instrucciones que son ejecutadas.
En Sql server podemos capturar las instrucciones y estadísticas de su ejecución como: tiempo que demoró, uso
de cpu, lecturas lógicas, entre otras. Los datos recogidos puede ser laborioso de analizarlas por la cantidad de
datos, por la variación de los parámetros y sus valores que son pasados a las instrucciones. Para poder
agruparlos vamos a usar “expresiones regulares”

1. Capturando instrucciones que demoran más de “X” segundos con “Extended Events” a un archivo.
2. Copiar la información de los “Extended Events” a tabla temporal global.
3. Usando “Expresiones regulares” para transformar los datos y poder agruparlos
4. Graficar los datos en Power Bi
1. Capturando instrucciones que demoran más de
“X” segundos con “Extended Events” a un
archivo.
En el servidor de base de datos crear un “Extended Events” para capturar las instrucciones que demoran más
de 1.5 segundos (este valor varía dependiendo el caso)

CREATE EVENT SESSION [LongRunningQueries] ON SERVER


ADD EVENT sqlserver.rpc_completed(SET collect_output_parameters=(1),collect_statement=(1)

ACTION(package0.collect_system_time,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.session_id,sqlserver.transaction_id,sqlserver.transacti
on_sequence,sqlserver.username)
WHERE ([duration]>(1500000))),
ADD EVENT sqlserver.sp_statement_completed(

ACTION(package0.collect_system_time,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.session_id,sqlserver.transaction_id,sqlserver.transacti
on_sequence,sqlserver.username)
WHERE ([duration]>(1500000))),
ADD EVENT sqlserver.sql_batch_completed(SET collect_batch_text=(1)

ACTION(package0.collect_system_time,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.session_id,sqlserver.transaction_id,sqlserver.transacti
on_sequence,sqlserver.username)
WHERE ([duration]>(1500000))),
ADD EVENT sqlserver.sql_statement_completed(

ACTION(package0.collect_system_time,sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.plan_handle,sqlserver.query_hash,sqlserver.session_id,sqlserver.transaction_id,sqlserver.transacti
on_sequence,sqlserver.username)
WHERE ([duration]>(1500000)))
ADD TARGET package0.event_file(SET filename=N'LongRunningQueries.xel',max_file_size=(50),max_rollover_files=(2))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)
GO
2. Copiar la información de los extended events a
tabla temporal global
La data del “Extended Event” copiarla a una tabla temporal global, luego de la tabla temporal global extraer
los campos que se necesite a otra tabla global.
• Tabla temporal porque puede no tenerse acceso para crear tablas.
• A una segunda tabla temporal para separar los datos a columnas que es mas fácil para revisar.
SELECT
event_data =convert(xml,event_data)
into ##eeTable
FROM sys.fn_xe_file_target_read_file(N'LongRunningQueries*.xel', NULL,NULL,NULL)
go
SELECT event_data.value('(event/@timestamp)[1]', N'datetime') as timestamp,
event_data.value('(/event/action[@name="database_name"]/value)[1]','nvarchar(max)') AS [Database],
event_data.value('(event/data[@name="statement"]/value)[1]', N'nvarchar(max)') as statement ,
event_data.value('(/event/action[@name="client_app_name"]/value)[1]', 'nvarchar(max)') as client_app_name,
event_data.value('(/event/action[@name="client_hostname"]/value)[1]', 'nvarchar(max)') as client_hostname,
event_data.value('(/event/data[@name="batch_text"]/value)[1]', 'nvarchar(max)') as batch_text,
event_data.value('(/event/data[@name="object_name"]/value)[1]', 'nvarchar(max)') as objectname,
event_data.value('(/event/data[@name="writes"]/value)[1]','varchar(max)') AS [writes],
event_data.value('(/event/data[@name="cpu_time"]/value)[1]', 'numeric(20)') as cpu_time,
event_data.value('(event/data[@name="duration"]/value)[1]', 'numeric(20)') as duration,
event_data.value('(/event/data[@name="logical_reads"]/value)[1]', 'numeric(20)') as logical_reads,
event_data.value('(/event/data[@name="physical_reads"]/value)[1]', 'numeric(20)') as physical_reads,
event_data.value('(/event/data[@name="result"]/value)[1]', 'nvarchar(max)') as result,
event_data.value('(/event/data[@name="row_count"]/value)[1]', 'numeric(20)') as row_count,
event_data.value('(/event/action[@name="session_id"]/value)[1]', 'nvarchar(max)') as session_id,
event_data.value('(/event/action[@name="transaction_id"]/value)[1]', 'nvarchar(max)’) as transaction_id,
event_data.value('(/event/action[@name="username"]/value)[1]', 'nvarchar(max)') as username
into ##eeTable2
FROM ##eeTable event_data
go
Si hay restricciones de acceso en producción

En entornos productivos puede haber restricciones para crear tablas, una opción es copiar la data a una base
de datos Access y luego copiarlo a una base de datos sql local para su revisión.
• Copiar la data una base de datos Access, escoger la opción “write a query to specify the data to transfer”
con el siguiente query “select * from ##eeTable2”.
• Después, de similar forma la data de Access copiarlo a una tabla física en una base de datos sql server para
realizar la revisión.
3. Usando las expresiones regulares para transformar
datos y poder agruparlos
En el siguiente link se encuentra los pasos para poder utilizar expresiones regulares en base de datos sql
server https://github.com/DevNambi/sql-server-regex/blob/master/install/sql-2016.md
Las expresiones regulares los utilizamos para poder agrupar las instrucciones que son invocados con
diferentes valores, en estos dos casos:
• Cadena ‘????..’ lo reemplazamos por 'ParametroString’
• Cadena =9999… lo reemplazamos por 9999
select Sql = dbo.RegexReplace(
dbo.RegexReplace(
case when [statement] is not null then statement
when a.batch_text is not null then batch_text
else ''
end
,'\''(/?[^‘’]+)\''','‘’ParametroString''')

,'=\s+\d(/?[^d]+)','=9999 ') ,
*
from Revisar a
GO
4. Graficar los datos en Power Bi
Con el uso de las expresiones regulares podemos fácilmente agruparlos por Database, Client_app_name y
sumarizando los campos de “duration”, “cpu_time”, “logical_reads”, estas gracias ayudan a identificar las
instrucciones que demandan mas uso de recursos del servidor de base de datos que serian los candidatos
para revisar y mejorarse.

También podría gustarte