1. GPI.- Confidencial
En este artículo analizaremos el comportamiento de las bases de datos cuando se le realizan
operaciones de Shrink. Algunos DBA’s realizan esta tarea de manera común sin percatarse
talves del grave daño que le están causando a la base de datos. Este ejemplo lo tome de la
explicación realizada por Paul Randal durante una conferencia en SQL Server Connections y
otros métodos de ingreso de datos proporcionados por Itzik Ben Gan.
Lo que haremos es crear una pequeña base de datos de prueba, la vamos a llenar con una serie
de datos de forma aleatoria, luego borramos la tabla de parámetros y realizamos el shrink para
ver los resultados finales.
USE MASTER;
GO
IF DATABASEPROPERTYEX ('shrinkdb', 'Version') > 0
DROP DATABASE shrinkdb;
Create database ShrinkDb;
Go
--Creamos luego una tabla llamada empleados
USE [Shrinkdb]
GO
-- Creamos una tabla auxiliar que va a servirnos para llenar datos aleatorios
SET NOCOUNT ON;
IF OBJECT_ID('dbo.Nums') IS NOT NULL
DROP TABLE dbo.Nums;
CREATE TABLE dbo.Nums(n INT NOT NULL PRIMARY KEY);
DECLARE @max AS INT, @rc AS INT;
SET @max = 1000000;
SET @rc = 1;
INSERT INTO dbo.Nums(n) VALUES(1);
WHILE @rc * 2 <= @max
BEGIN
INSERT INTO dbo.Nums(n) SELECT n + @rc FROM dbo.Nums;
SET @rc = @rc * 2;
END
INSERT INTO dbo.Nums(n)
SELECT n + @rc FROM dbo.Nums WHERE n + @rc <= @max;
GO
-- Parámetros de configuración para cargas posteriores
DECLARE
@numorders AS INT,
@numcusts AS INT,
@numemps AS INT,
@numshippers AS INT,
@numyears AS INT,
Tel: (506) 297 8132 – 244-5849 | De la Basílica de Santo Domingo, Heredia; 200 mts norte y 900 mts este. Apto 103-1100, Costa Rica
2. GPI.- Confidencial
@startdate AS DATETIME;
SELECT
@numorders = 1000000,
@numcusts = 20000,
@numemps = 3500,
@numshippers = 5,
@numyears = 4,
@startdate = '20050101';
-- Creamos y llenamos la tabla de empleados con un maximo de 3500 empleados,
las variables de arriba permiten cambiar dichos parámetros
CREATE TABLE dbo.Empleados
(
empid INT NOT NULL,
Apellido NVARCHAR(25) NOT NULL,
Nombre NVARCHAR(25) NOT NULL
CONSTRAINT PK_empleados PRIMARY KEY(empid)
);
INSERT INTO dbo.Empleados(empid, Apellido, Nombre)
SELECT n AS empid,
N'Apellido_' + CAST(n AS NVARCHAR(10)) AS Apellido,
N'Nombre_' + CAST(n AS NVARCHAR(10)) AS Nombre
FROM dbo.Nums
WHERE n <= @numemps;
CREATE NONCLUSTERED INDEX INX_APE ON EMPLEADOS (APELLIDO)
/*
Aca podemos chequear los datos de la tabla para que revisen los datos
cargados
*/
SELECT * FROM Empleados
--Chequeamos el porcentaje de fragmentación de la tabla para medir como se
encuentra el índice.
SELECT avg_fragmentation_in_percent, fragment_count FROM
sys.dm_db_index_physical_stats (
DB_ID ('shrinkdb'), OBJECT_ID ('empleados'), 1, NULL, 'LIMITED');
GO
Tel: (506) 297 8132 – 244-5849 | De la Basílica de Santo Domingo, Heredia; 200 mts norte y 900 mts este. Apto 103-1100, Costa Rica
3. GPI.- Confidencial
--Como podemos ver el índice no muestra fragmentación considerable. Este debe
de ser el comportamiento normal
-- Ahora borramos la tabla NUMS que utilizamos como utilitario previamente
DROP TABLE nums;
GO
-- hacemos el shrink de la base de datos para "recuperar" espacio en disco
DBCC SHRINKDATABASE (shrinkdb);
GO
-- Chequeamos la fragmentación nuevamente
SELECT avg_fragmentation_in_percent, fragment_count FROM
sys.dm_db_index_physical_stats (
DB_ID ('shrinkdb'), OBJECT_ID ('empleados'), 1, NULL, 'LIMITED');
GO
/*
Ahora como pueden ver, resulta ser que el indice esta totalmente fragmentado,
y esto se debe a que
el Shrink inicia el proceso desde el final del archivo de datos hacia el
inicio, lo que hace que el orden
Tel: (506) 297 8132 – 244-5849 | De la Basílica de Santo Domingo, Heredia; 200 mts norte y 900 mts este. Apto 103-1100, Costa Rica
4. GPI.- Confidencial
de las paginas cambie y se fragmente. Y esto q provoca? Rendimiento pésimo de
la base de datos, encolamiento en
discos, mayor consumo de recursos en general... asi que acá les dejo la
inquietud y cuando algún DBA les
diga que va a hacer un shrink en Producción... YA SABEN Q HACER... :)
*/
Tel: (506) 297 8132 – 244-5849 | De la Basílica de Santo Domingo, Heredia; 200 mts norte y 900 mts este. Apto 103-1100, Costa Rica