En general, cuando trabajas con tablas de gran tamaño, los problemas de rendimiento (desde el punto de vista de almacenamiento) se dan por dos motivos:
1. Leer un rango de valores, es decir, si el resultado de un select con una condición where sobre un campo indexado devuelve más de un 15% (aprox) de los registros totales, el optimizador decide que es más eficiente resolver la consulta con la operación fullscan (recorrer toda la tabla) en vez de utilizar el índice con las operaciones index-range o index-seek. En este caso, particionar (almacenar la tabla en diferentes segmentos físicos) puede mejorar el rendimiento, por ejemplo: si tienes la tabla Facturas con el campo FechaFacturacion, puedes definir una partición por cada año de FechaFacturación, de esta manera, una consulta por rangos que pida todas las facturas del año 2010 (where FechaFacturación = 2010) se resuelve con un fullscan de una partición en vez de un fullscan de toda la tabla.
2. Alta concurrencia, si el almacenamiento físico total de la tabla recae sobre un único disco del servidor, las diferentes operaciones para acceder a los datos se resolverán en forma serial, no en paralelo, lo que puede provocar congestiones de I/O. En este caso, si el servidor tiene múltiples discos, puedes utilizarlos para distribuir las tablas creando filegroups (espacio de almacenamiento lógico que define la relación entre los ficheros de la base de datos y el sistema operativo), por ejemplo: separar las tablas en función del uso, las de mayor acceso en los discos rápidos y las de menor acceso en los lentos.
Este es un código de ejemplo que combina los dos casos, particionar una tabla y almacenar cada partición en un filegroup diferente.
Código:
--crear una base de datos
create database demo
go
--crear los filegroup f1, f2 y f3
alter database demo add filegroup f1
go
alter database demo add filegroup f2
go
alter database demo add filegroup f3
go
--agregar un fichero al filegroup f1 en el disco c:
alter database demo add file (
name = demo_f1_dat01,
filename = 'c:\mssql\data\demo_f1_dat01.ndf',
size = 500mb
)
to filegroup f1
go
--agregar un fichero al filegroup f2 en el disco d:
alter database demo add file (
name = demo_f2_dat01,
filename = 'd:\mssql\data\demo_f2_dat01.ndf',
size = 500mb
)
to filegroup f2
go
--agregar un fichero al filegroup f3 en el disco e:
alter database demo add file (
name = demo_f3_dat01,
filename = 'e:\mssql\data\demo_f3_dat01.ndf',
size = 500mb
)
to filegroup f3
go
Código:
--crear un modelo de particion.
--sirve para campos datetime, y crea 3 particiones donde:
--los valores menores a 20100101 van a la partición 1
--los valores entre 20100101 y 20110101 a la particion 2
--y los valores mayores 20110101 a la particion 3
create partition function f_facturas_partition (datetime)
as range left
for values ('20100101','20110101')
go
--crear un esquema que defina en que filegroup
--se almacena cada particion.
--puedes tener todas las particiones en un mismo filegroup,
--o como este caso, una partición por filegroup.
create partition scheme s_facturas_partition
as partition f_facturas_partition
to (f1, f2, f3)
go
--finalmente, crear la tabla definiendo sobre que campo
--se particionan los datos.
create table facturas
(id_factura int,
fecha_factura datetime)
on s_facturas_partition (fecha_factura)
go
De todos modos, debes tener en mente que esto son aspectos físicos, no lógicos, y no tiene impacto en el modelo de datos o la estructura de las sentencias SQL, una consulta sobre una tabla devuelve el mismo resultado, esté particionada o no. En general, son decisiones que toma un DBA en el proceso de tunning para entornos de test o producción, rara vez forma parte del diseño o desarrollo del sistema.
Saludos