El siguiente paso fue la DATA, para realizar las pruebas necesitamos datos, una base lo suficientemente grande como para que las actividades que realizaramos mostraran resultados medibles.
La Bestia es una maquina bastante poderosa, asi que esta base no deberia ser pequeña.
El modelo
La empresa ficticia es de desarrollo y venta de software. Nuestra base esta compuesta por 5 tablas.
Desarrollador: Esta tabla contiene los datos de los 103 desarrolladores.
CREATE TABLE [dbo].[DESARROLLADOR](
[IDDESARROLLADOR] [int] NOT NULL,
[NOMBREDEV] [varchar](100) NOT NULL,
CONSTRAINT [PK_DESARROLLADOR] PRIMARY KEY NONCLUSTERED
(
[IDDESARROLLADOR] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
Aplicacion: Nuestros desarrolladores han desarrollado 553 Aplicaciones.
CREATE TABLE [dbo].[APLICACION](
[IDSOFTWARE] [int] NOT NULL,
[IDDESARROLLADOR] [int] NOT NULL,
[DESCRIPCION] [varchar](250) NULL,
[VERSION] [varchar](10) NULL,
[NOMBRESW] [varchar](100) NULL,
CONSTRAINT [PK_APLICACION] PRIMARY KEY NONCLUSTERED
(
[IDSOFTWARE] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
Clientes: Durante el tiempo que ha estado funcionando la empresa, hemos tenido 31224 Clientes
CREATE TABLE [dbo].[CLIENTE](
[CODIGOCLIENTE] [int] NOT NULL,
[RUT] [int] NULL,
[NOMBRECLIENTE] [varchar](100) NULL,
CONSTRAINT [PK_CLIENTE] PRIMARY KEY NONCLUSTERED
(
[CODIGOCLIENTE] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
Facturas: Hemos vendido 2 millones de facturas a nuestros clientes, como los productos son muy bueno :P
CREATE TABLE [dbo].[FACTURA](
[NUMEROFACTURA] [int] NOT NULL,
[CODIGOCLIENTE] [int] NOT NULL,
[FECHA] [datetime] NULL,
CONSTRAINT [PK_FACTURA] PRIMARY KEY NONCLUSTERED
(
[NUMEROFACTURA] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
Licencias: En cada factura podemos tener una o mas licencias, no se cuantas licencias se han vendido........... aun :D
CREATE TABLE [dbo].[LICENCIA](
[IDLICENCIA] [int] NOT NULL,
[CODIGOCLIENTE] [int] NOT NULL,
[IDSOFTWARE] [int] NOT NULL,
[NUMEROFACTURA] [int] NOT NULL,
[LICENCIA] [uniqueidentifier] NOT NULL CONSTRAINT [DF_LICENCIA_LICENCIA] DEFAULT (newid()),
CONSTRAINT [PK_LICENCIA] PRIMARY KEY NONCLUSTERED
(
[IDLICENCIA] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO
ya con el modelo se definieron algunas relaciones entre las tablas a través de llaves foráneas.
ALTER TABLE [dbo].[LICENCIA] WITH CHECK ADD CONSTRAINT [FK_LICENCIA_DETALLE_F_FACTURA] FOREIGN KEY([NUMEROFACTURA])
REFERENCES [dbo].[FACTURA] ([NUMEROFACTURA])
GO
ALTER TABLE [dbo].[LICENCIA] WITH CHECK ADD CONSTRAINT [FK_LICENCIA_RELATIONS_CLIENTE] FOREIGN KEY([CODIGOCLIENTE])
REFERENCES [dbo].[CLIENTE] ([CODIGOCLIENTE])
GO
ALTER TABLE [dbo].[LICENCIA] WITH CHECK ADD CONSTRAINT [FK_LICENCIA_VENTA_DE__APLICACI] FOREIGN KEY([IDSOFTWARE])
REFERENCES [dbo].[APLICACION] ([IDSOFTWARE])
GO
ALTER TABLE [dbo].[FACTURA] WITH CHECK ADD CONSTRAINT [FK_FACTURA_COMPRAS_CLIENTE] FOREIGN KEY([CODIGOCLIENTE])
REFERENCES [dbo].[CLIENTE] ([CODIGOCLIENTE])
GO
ALTER TABLE [dbo].[APLICACION] WITH CHECK ADD CONSTRAINT [FK_APLICACI_RELATIONS_DESARROL] FOREIGN KEY([IDDESARROLLADOR])
REFERENCES [dbo].[DESARROLLADOR] ([IDDESARROLLADOR])
GO
Para la generacion de los datos, de las tablas mas pequeñas, desarrollador y aplicacion, se uso excel, despues esos datos fueron cargados, el archivo generado en excel tenia lineas como las siguientes:
insert into desarrollador (idDesarrollador, NOMBREdev) values (1,'luis rivas')
insert into desarrollador (idDesarrollador, NOMBREdev) values (2,'robinson barruylle')
insert into desarrollador (idDesarrollador, NOMBREdev) values (3,'matilde piñats')
insert into desarrollador (idDesarrollador, NOMBREdev) values (4,'josefina parada')
insert into desarrollador (idDesarrollador, NOMBREdev) values (5,'jeanette antipan')
insert into desarrollador (idDesarrollador, NOMBREdev) values (6,'josé bravo')
Sin embargo al usar el mismo metedo para cargar la tabla de clientes se nos fueron los tiempos a la chuña. Habiamos generado 65.xxx clientes, sin embargo ya llevabamos media hora cargandolos y cortamos el script quedando cargados solo 32.xxx. El script de poco mas de 6Mb se guardo para usarlo despues en las pruebas.
Nos quedaba la carga de los 2 millones de facturas con sus detalles de licencias y este metodo no nos serviria, a menos que quisieramos quedarnos toda la semana cargando los datos :P
Generamos 2 scripts, uno en Transact-SQL, el otro creo que el awk, pero el que se uso fue el de SQL ya que el de awk generaria las lineas de insert y estariamos en el mismo punto anterior.
El script usado fue el siguiente:
DECLARE @counter int;
DECLARE @cliente int;
DECLARE @nlic int;
SET @counter = 1;
WHILE @counter <= 2000000
BEGIN
SET @cliente = (RAND()* 31224);
INSERT INTO dbo.FACTURA (NUMEROFACTURA,CODIGOCLIENTE,FECHA) VALUES (@counter,@cliente,getdate())
SET @nlic = (RAND()* 12);
WHILE @nlic >= 1
BEGIN
INSERT INTO dbo.LICENCIA (CODIGOCLIENTE,IDSOFTWARE,NUMEROFACTURA) VALUES (@cliente,(RAND()* 553),@counter)
@nlic = @nlic - 1
END
SET @counter = @counter + 1
END;
GO
Despues de poco mas de 1 hora ejecutandose llevabamos mas de 110000 facturas y mas de 730000 licencias por lo que lo dejamos y procedimos a retirarnos para continuar otro dia.
Durante el ultimo proceso tomamos algunas muestras de los contadores de performance los cuales les comento a continuacion, teniamos 2 sesiones terminal server abiertas, en una de ellas trabajaba Chubasco y en la otra yo, el script se estaba ejecutando en mi sesion.
Tiempo de la muestra: 31 de Enero 2009 entre las 16:30 y las 17:45
Processor: %Processor Time: _Total : llego a un maximo de 3,4 durante el proceso.
La grafica anterior nos muestra una linea azul que representa el promedio de la cola al disco Logico donde tenemos el archivo de Data, cuando comenzo la carga describio una curva que fue creciendo hasta llegar mas o menos a 1,6 y alli pareciera que se mantiene mas o menos constante, si agregamos a la grafica los valores de los discos fisicos tenemos una curva que coincide.
Respecto a la memoria, observamos que esta va decreciendo en la medida que vamos cargando los datos.
Podemos observar una caida fuerte, esta caida se debio a la ejecucion de una query que me mostraba la informacion de las lineas de licencias que llevabamos hasta ese momento.
La query ejecutada fue la siguiente:
SELECT dbo.APLICACION.NOMBRESW, dbo.CLIENTE.RUT, dbo.CLIENTE.NOMBRECLIENTE, dbo.APLICACION.VERSION, dbo.APLICACION.DESCRIPCION,
dbo.DESARROLLADOR.NOMBREDEV, dbo.FACTURA.NUMEROFACTURA, dbo.LICENCIA.LICENCIA
FROM dbo.FACTURA
INNER JOIN dbo.CLIENTE ON dbo.FACTURA.CODIGOCLIENTE = dbo.CLIENTE.CODIGOCLIENTE
INNER JOIN dbo.LICENCIA ON dbo.FACTURA.NUMEROFACTURA = dbo.LICENCIA.NUMEROFACTURA
INNER JOIN dbo.APLICACION ON dbo.LICENCIA.IDSOFTWARE = dbo.APLICACION.IDSOFTWARE
INNER JOIN dbo.DESARROLLADOR ON dbo.APLICACION.IDDESARROLLADOR = dbo.DESARROLLADOR.IDDESARROLLADOR
GO
Demorando 14 segundos y devolviendo cerca de 600000 lineas.
El tamaño del archivo de Data crecia en la medida que los datos se iban ingresando, este crecimiento no solo es de los datos, si se fijan en la figura enterior del reporte de tamaño de las tablas que fue tomado durante el proceso veran que el espacio usado por los indices incluso es mayor al usado por los datos. Los indices en las bases de datos es un tema interesante que da para mas de un futuro articulo :D
Las transacciones que se ejecutaba por segundo en esta sesion fluctuaban entre 162 a 166.
Eso es lo que les puedo contar por ahora. Si tiene curiosidad sobre algun contador que no inclui, coloquenlo en los comentarios, lo mismo si tienen alguna query interesante que podriamos agregar al set de pruebas final.
Saludos!!
Isa