A qué recursos está esperando el servidor (Versión SQL Server 2000 y anterior)
Introducción
En Solid Quality estamos realizando una serie de Summits por Latam (http://learning.solidq.com/la/CourseDetail.aspx?CourseScheduleId=211). El viernes pasado tuvimos el primero en Costa Rica, y próximamente estaremos en México, Colombia y Perú. Aunque no presencialmente, tengo la suerte de haber sido invitado a estos eventos como ponente. Me encuentro en España, y a través de Livemeeting, puedo contar a los asistentes a los Summits mis experiencias desde mi hogar en Torrevieja
Bueno, el tema es que este viernes, tuve la primera presentación, y aunque la presentación estaba focalizada en SQL Server 2005:
"SQL Server: Optimización y Afinamiento de servidores SQL Server: Al atender esta sesión, brindaremos las mejores prácticas para el análisis de rendimiento de servidores de bases de datos SQL Server 2005. Aprenderá a monitorear el uso de los recursos de su servidor (procesador, memoria, unidades IO, …) y mediante nuevas funciones de administración (DMVs), SQL Profiler y Performance Monitor mostraremos como identificar las consultas que más impacto tienen en su sistema para atacar los problemas de rendimiento desde su raíz. Muchas de las prácticas que presentaremos son aprendidas directamente del equipo que desarrolló el producto."
Estuve haciendo bastantes referencias a SQL Server 2000 porque:
Muchos de los asistentes trabajan con SQL Server 2000.
Nuestra experiencia en clientes dice que todavía hay muchos clientes con SQL Server 2000.
El mismo artículo lo tengo publicado para SQL Server 2005 en las siguientes URLs:
http://blogs.solidq.com/ES/erincon/Lists/Posts/Post.aspx?ID=28
http://solidqualitylearning.com/Blogs/eladio/archive/2007/02/22/3727.aspx
Me comprometí con los asistentes a publicar el mismo script para SQL Server 2000, así que ahí va:
El procedimiento almacenado
Para vuestra información he tenido que realizar los siguientes cambios:
Quitar referencia a CTE (obviamente en SQL Server 2000 no existe).
Quitar referencia a DMV y utilizar el correspondiente comando DBCC.
Cambiar tabla variable por tabla temporal porque un comando DBCC no puede insertar en una tabla variable.
Filtrar del resultado del comando DBCC el wait_type "Total" que es la suma total de los valores medidos.
Ejemplo de ejecución:
EXEC dbo.sproc_get_waitstats_percentage
@hours = null,
@minutes = 5,
@seconds = null
El procedimiento almacenado:
IF EXISTS (SELECT * FROM sysobjects WHERE name = 'sproc_get_waitstats_percentage')
DROP PROC dbo.sproc_get_waitstats_percentage
GO
CREATE PROC dbo.sproc_get_waitstats_percentage
@hours tinyint = null,
@minutes tinyint = null,
@seconds tinyint = null
AS
SET NOCOUNT ON
IF @hours IS NULL
SET @hours = 0
IF @minutes IS NULL
SET @minutes = 0
IF @seconds IS NULL
SET @seconds = 0
--
-- Validaciones iniciales
--
IF @hours < 0 OR @hours > 24
BEGIN
RAISERROR ('Hours range is not valid.', 16, 1 )
RETURN
END
IF @minutes < 0 OR @minutes > 60
BEGIN
RAISERROR ('Minutes range is not valid.', 16, 1 )
RETURN
END
IF @seconds < 0 OR @seconds > 60
BEGIN
RAISERROR ('Seconds range is not valid.', 16, 1 )
RETURN
END
IF @hours = 0 and @minutes = 0 and @seconds = 0
BEGIN
RAISERROR ('The measure time must be greater than zero.', 16, 1 )
RETURN
END
--
-- Definición de variable table
--
CREATE TABLE #T (
id int identity
, wait_type nvarchar(60)
, Requests bigint
, Wait_Time bigint
, signal_Wait_Time bigint)
--
-- Inserción de captura inicial
--
INSERT #T
EXEC ('DBCC SQLPERF(WAITSTATS)')
--
-- A esperar n tiempo
--
DECLARE @s CHAR(8)
SET @s =
RIGHT ('00' + CAST (@hours as VARCHAR(2)), 2) + ':'
+ RIGHT ('00' + CAST (@minutes as VARCHAR(2)), 2) + ':'
+ RIGHT ('00' + CAST (@seconds as VARCHAR(2)), 2)
WAITFOR DELAY @s
--
-- Inserción de segunda captura
--
INSERT #T
EXEC ('DBCC SQLPERF(WAITSTATS)')
--
-- calculos finales
--
SELECT
detalle.*
, detalle.Wait_Time * 1.00 / detalle.Requests as wait_per_request
, CASE WHEN suma.Requests = 0 THEN 0 ELSE detalle.Requests * 1.00 / suma.Requests END as porcen_Requests
, CASE WHEN suma.Wait_Time = 0 THEN 0 ELSE detalle.Wait_Time * 1.00 / suma.Wait_Time END as porcen_Wait_Time
, CASE WHEN suma.signal_Wait_Time = 0 THEN 0 ELSE detalle.signal_Wait_Time * 1.00 / suma.signal_Wait_Time END as porcen_signal_Wait_Time
FROM
(SELECT * FROM ( SELECT
T1.wait_type
, AVG(T2.Requests - T1.Requests) Requests
, AVG(T2.Wait_Time - T1.Wait_Time) Wait_Time
, AVG(T2.signal_Wait_Time - T1.signal_Wait_Time) signal_Wait_Time
FROM #T t1
JOIN #T t2
ON T1.wait_type = T2.wait_type
AND T1.id < T2.id
WHERE T1.wait_type <> 'Total'
GROUP BY T1.wait_type
) v WHERE
v.Wait_Time <> 0
) detalle,
( SELECT
SUM (T2.Requests - T1.Requests) Requests
, SUM (T2.Wait_Time - T1.Wait_Time) Wait_Time
, SUM (T2.signal_Wait_Time - T1.signal_Wait_Time) signal_Wait_Time
FROM #T t1
JOIN #T t2
ON T1.wait_type = T2.wait_type
AND T1.id < T2.id
WHERE T1.wait_type <> 'Total'
) suma
GO
Siéntete libre de publicar comentarios…