Particionamiento de tablas

Particionamiento de tablas de bases de datos en SQL Server

Particionar es el proceso donde tablas muy grandes son divididas en múltiples partes más pequeñas. Al separar una tabla grande en tablas individuales más pequeñas, las consultas que acceden sólo a una fracción de los datos pueden correr más rápido porque hay menos datos que escanear. El objetivo principal de particionar es ayudar en el mantenimiento de tablas grandes y reducir el tiempo de respuesta general para leer y cargar datos para operaciones SQL particulares.

Veamos el ejemplo de la tabla EmpleadosR :
---Primeramente creamos la base de datos BDParticion
CREATE DATABASE [BD_FP]
 CONTAINMENT = NONE
 ON  PRIMARY
( NAME = N'BD_FP', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\BD_FP.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
 LOG ON
( NAME = N'BD_FP_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\BD_FP_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
GO

--Creamos la Tabla EmpleadosR en la base de datos BD_FP
use BD_FP
go

cREATE TABLE EmpleadosR
(
ReportID int IDENTITY (1,1) NOT NULL,
ReportName varchar (100),
ReportNumber varchar (20),
ReportDescription varchar (max)
CONSTRAINT EReport_PK PRIMARY KEY CLUSTERED (ReportID)
)

--Insertamos informacion en la tabla EmpleadosR
DECLARE @i int
SET @i = 1

BEGIN TRAN
WHILE @i<100000
BEGIN
INSERT INTO EmpleadosR
(
ReportName,
ReportNumber,
ReportDescription
)
VALUES
(
'ReportName',
CONVERT (varchar (20), @i),
REPLICATE ('Report', 1000)
)
SET @i=@i+1
END
COMMIT TRAN
GO


--Si corremos una consulta SQL para recuperar los datos de ReportID, ReportName, ReportNumber de la tabla EmployeeReports
--l resultado establece que la cuenta del escaneo es 5
-- representa un número de veces que la tabla ha sido accedida durante la consulta,
-- que teníamos 113288 lecturas lógicas que representan el número total de accesos de páginas para procesar la consulta:


SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT er.ReportID, er.ReportName, er.ReportNumber
FROM dbo.EmpleadosR er
WHERE er.ReportNumber LIKE '%33%'
SET STATISTICS IO OFF
SET STATISTICS TIME OFF

A continuación crearemos la tabla ReportsDesc y moveremos la columna ReportDescription y la tablaReportsData y moveremos todos los datos de la tabla EmployeeReports excepto la columnaReportDescription.
CREATE TABLE ReportesD
( ReportID int FOREIGN KEY REFERENCES EmpleadosR (ReportID),
  ReportDescription varchar(max)
  CONSTRAINT PK_ReportDesc PRIMARY KEY CLUSTERED (ReportID)
 )

CREATE TABLE ReportesData
(
ReportID int NOT NULL,
ReportName varchar (100),
ReportNumber varchar (20),

CONSTRAINT DReport_PK PRIMARY KEY CLUSTERED (ReportID)
)
INSERT INTO dbo.ReportesData
(
    ReportID,
    ReportName,
    ReportNumber
)
SELECT er.ReportID,
er.ReportName,
er.ReportNumber
FROM dbo.EmpleadosR er


SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT er.ReportID, er.ReportName, er.ReportNumber
FROM ReportesData er
WHERE er.ReportNumber LIKE '%33%'
SET STATISTICS IO OFF
SET STATISTICS TIME OFF



La partición vertical en tablas SQL Server puede no ser el método correcto en cada caso. Sin embargo, si usted tiene, por ejemplo, una tabla con muchos datos que no se accede igualitariamente, tablas con datos a los que desea restringir el acceso, o escaneos que retornan muchos datos, la partición vertical puede ayudar.

Particionamiento Horizontal en tablas SQL Server

El particionamiento horizontal divide una tabla en múltiples tablas que contienen el mismo número de columnas, pero menos filas. Por ejemplo, si una tabla contiene un gran número de filas que representan reportes mensuales podría ser particionada horizontalmente en tablas por años, con cada tabla representando todos los reportes para un año específico. De esta manera las consultas que requieren datos para un año específico sólo referenciarán la tabla apropiada. Las tablas deberían ser particionadas en una manera que las consultas referencian tan pocas tablas como sea posible.
Las tablas son particionadas horizontalmente basadas en una columna que será usada para particionar y los rangos asociados a cada partición. La columna de particionamiento es usualmente una columna de fecha pero todos los tipos de datos que son válidos para usarse como columnas de índice pueden ser usados como columna de partición, excepto columnas timestamp. Los siguientes tipos de datos no pueden ser especificados: ntext, text, image, xml, varchar(max), nvarchar(max), o varbinary(max), el tipo definido por el usuario Microsoft .NET Framework common language runtime (CLR), columnas de tipo de datos de alias.
Hay dos enfoques diferentes que podríamos usar para lograr la partición de la tabla. El primero es crear una nueva tabla particionada y simplemente copiar los datos desde su tabla existente en la nueva tabla y renombrarla. El segundo enfoque es particionar una tabla existente reconstruyendo o creando un índice agrupado en la tabla.

Ejemplo de particionamiento horizontal con la creación de una nueva tabla particionada

SQL Server 2005 introdujo una característica incorporada de particionamiento para particionar horizontalmente una tabla con hasta 1000 particiones en SQL Server 2008 y 15000 particiones en SQL Server 2012, y el emplazamiento de los datos es manejado automáticamente por SQL Server. Esta característica está disponible sólo en la Edición Enterprise de SQL Server.
Para crear una tabla particionada para almacenar reportes mensuales primero crearemos grupos de archivos adicionales. Un grupo de archivos es una unidad de almacenamiento lógica. Cada base de datos tiene un grupo de archivos que contiene el archivo de datos primario (.mdf). Un grupo de archivos adicional y definido por el usuario puede ser creado para contener archivos secundarios (.ndf). Nosotros crearemos 12 grupos de archivos por cada mes: Para verificar los grupos de archivos creados y disponibles en la base de datos actual ejecute la siguiente consulta:
ALTER DATABASE BD_FP
ADD FILEGROUP Enero
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Febrero
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Marzo
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Abril
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Mayo
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Junio
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Julio
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Agosto
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Septiembre
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Octubre
GO
ALTER DATABASE BD_FP
ADD FILEGROUP Noviembre
GO
ALTER DATABASE BD_FP
ADD FILEGROUP diciembre
GO



1
2
3
SELECT name AS AvailableFilegroups
FROM sys.filegroups
WHERE type = 'FG'
Cuando son creados grupos de archivos añadiremos el archivo .ndf a cada grupo de archivos: De la misma manera los archivos a todos los grupos de archivos creados especificando el nombre lógico del archivo y el nombre del archivo del sistema operativo (físico) para cada grupo de archivos. Por ejemplo:

ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartEnero],
    FILENAME = 'C:\SQL\BD_FP.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Enero]


ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartFebrero],
    FILENAME = 'C:\SQL\BD_FP2.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Febrero]

ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartMarzo],
    FILENAME = 'C:\SQL\BD_FP3.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Marzo]


ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartAbril],
    FILENAME = 'C:\SQL\BD_FP4.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Abril]


ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartMayo],
    FILENAME = 'C:\SQL\BD_FP5.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Mayo]


ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartJunio],
    FILENAME = 'C:\SQL\BD_FP6.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Junio]

ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartJulio],
    FILENAME = 'C:\SQL\BD_FP7.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Julio]


ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartAgosto],
    FILENAME = 'C:\SQL\BD_FP8.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Agosto]


      
ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartSeptiembre],
    FILENAME = 'C:\SQL\BD_FP9.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Septiembre]

ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartOctubre],
    FILENAME = 'C:\SQL\BD_FP10.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Octubre]


ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartNoviembre],
    FILENAME = 'C:\SQL\BD_FP11.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Noviembre]


      
ALTER DATABASE [BD_FP]
    ADD FILE
    (
    NAME = [PartDiciembre],
    FILENAME = 'C:\SQL\BD_FP12.ndf',
        SIZE = 3072 KB,
        MAXSIZE = UNLIMITED,
        FILEGROWTH = 1024 KB
    ) TO FILEGROUP [Diciembre]




 Para verificar archivos creado añadidos a los grupos de archivos ejecute la siguiente consulta:
SELECT
name as [FileName],
physical_name as [FilePath]
FROM sys.database_files
where type_desc = 'ROWS'
GO

 Dialog showing name and path for files created added to the filegroups
Después de crear grupos de archivos adicionales para almacenar datos crearemos una función de partición. Una función de partición es una función que mapea las filas de una tabla particionada en particiones basada en los valores de una columna de partición. En este ejemplo crearemos una función de partición que particiona una tabla en 12 particiones, una por cada mes de los valores de un año en una columna de fecha:

CREATE PARTITION FUNCTION [PartitioningByMonth] (datetime)
AS RANGE RIGHT FOR VALUES ('20140201', '20140301', '20140401',
               '20140501', '20140601', '20140701', '20140801',
               '20140901', '20141001', '20141101', '20141201');
Para mapear las particiones de una tabla particionada a grupos de archivos y determinar el número y dominio de las particiones de una tabla crearemos un esquema de partición:
CREATE PARTITION SCHEME PartitionBymonth
AS PARTITION PartitioningBymonth
TO (Enero, Febrero, Marzo,
    Abril, Mayo, Junio, Julio,
    Agosto, Septiembre, Octubre,
    Noviembre, Diciembre);




Ahora vamos a crear la tabla usando el esquema de partición PartitionBymonth, y la llenaremos con datos de prueba:
CREATE TABLE Reportes
(ReportDate datetime PRIMARY KEY,
MonthlyReport varchar(max))
ON PartitionBymonth (ReportDate);
GO

INSERT INTO Reportes(ReportDate,MonthlyReport)
SELECT '20140105', 'ReportEnero' UNION ALL
SELECT '20140205', 'ReportFebryary' UNION ALL
SELECT '20140308', 'ReportMarzo' UNION ALL
SELECT '20140409', 'ReportAbril' UNION ALL
SELECT '20140509', 'ReportMayo' UNION ALL
SELECT '20140609', 'ReportJunio' UNION ALL
SELECT '20140709', 'ReportJulio' UNION ALL
SELECT '20140809', 'ReportAugust' UNION ALL
SELECT '20140909', 'ReportSeptiembre' UNION ALL
SELECT '20141009', 'ReportOctubre' UNION ALL
SELECT '20141109', 'ReportNoviembre' UNION ALL
SELECT '20141209', 'Reportdiciembre'

Ahora verificaremos las filas en las diferentes particiones:


SELECT
p.partition_number AS PartitionNumber,
f.name AS PartitionFilegroup,
p.rows AS NumberOfRows
FROM sys.partitions p
JOIN sys.destination_data_spaces dds ON p.partition_number = dds.destination_id
JOIN sys.filegroups f ON dds.data_space_id = f.data_space_id
WHERE OBJECT_NAME(OBJECT_ID) = 'Reportes'



Ahora simplemente copie los datos desde su tabla y renombre una tabla particionada.


Comentarios

Entradas populares