web-dev-qa-db-fra.com

Comment partitionner une table par mois ("Both" YEAR & MONTH) et créer automatiquement des partitions mensuelles?

J'essaie de partitionner une table à la fois Year et Month. La colonne à travers laquelle je vais partitionner est une colonne de type datetime avec un format ISO ('20150110', 20150202 ', etc.).

Par exemple, j'ai des données de ventes pour 2010, 2011, 2012. J'aimerais que les données soient partitionnées par année et chaque année également par mois. (2010/01, 2010/02, ... 2010/12, 2011/01, ... 2015/01 ...)

EX:

Sales2010Jan, Sales2010Feb, Sales2011Jan, Sales2011Feb, Sales2012Dec, etc.

Ma question est: est-ce même possible? Si c'est le cas, comment puis-je automatiser le processus à l'aide de SSIS?

10
Amr Tharwat

SSIS est un ETL (extraire, transformer, charger). Ce n'est pas ce que tu veux faire. Il vous suffit de créer dynamiquement des instructions DDL.

Je travaille avec le quart ci-dessous mais ça marche aussi avec 1, 2 ou X mois si vous voulez.

Si vous souhaitez partitionner la table, vous devez d'abord créer le fichier, les groupes de fichiers et la table partitionnée et définir le partitionnement manuellement

Création de N + 1 partitions pour le T1 2015 (avant, Q1 et après Q2) sur une table avec un PK d'identité int et une colonne partitionnée datetime2. Mettez-le à jour pour ajouter des mois, faites-le tous les mois ou tout ce dont vous avez besoin ...

  • Créez d'abord N groupes de fichiers:

    Alter Database [Test] Add Filegroup [Part_Before2015]
    Go
    Alter Database Test Add Filegroup [Part_201501]
    Go
    Alter Database Test Add Filegroup [Part_201504]
    Go
    
  • Ajoutez un fichier pour chaque groupe de fichiers:

    Alter Database [Test] Add FILE ( NAME = N'Part_Before2015', FILENAME = N'...\Part_Before2015.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ) TO Filegroup [Part_Before2015]
    Alter Database [Test] Add FILE ( NAME = N'Part_201501', FILENAME = N'...\Part_201501.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ) TO Filegroup [Part_201501]
    Alter Database [Test] Add FILE ( NAME = N'Part_201504', FILENAME = N'...\Part_201504.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ) TO Filegroup [Part_201504]
    
  • Créez une fonction de partition sur un type datetime2 (ou date ou même datetime):

    Create Partition Function RangePartFunction (datetime2)
    as Range Right For Values ('20150101', '20150401') 
    
  • Créez un schéma de partition en utilisant la fonction de partition sur chaque groupe de fichiers (N + 1):

    Create Partition Scheme RangePartScheme as Partition RangePartFunction
    To ([Part_Before2015], [Part_201501], [Part_201504])
    
  • Créez la table partitionnée sur son schéma de partition:

    Create TABLE [PartitionTable] (id int identity(0, 1) not null, date datetime2 not null, text char(8000))
    On RangePartScheme (date) ;
    
  • Ajoutez un index clusterisé sur la colonne partitionnée et le schéma de partition:

    Create Clustered Index IDX_Part On dbo.PartitionTable(date) 
        On RangePartScheme (date);
    
  • Ajoutez un PK à la colonne id:

    Alter Table dbo.PartitionTable Add COntraint PK_Part Primary Key Nonclustered(id, date);
    

Générez la requête utilisée pour ajouter des groupes de fichiers supplémentaires après la limite droite et divisez la dernière partition

  • Examiner l'extension du schéma de partition et la division des fonctions de partition
  • Examen DMV utilisé
  • Passez en revue tout cela et comment l'utiliser pour créer du SQL dynamique

    Declare @currentDate datetime2
    Declare @endDate datetime2 = '20160701' -- new end date
    Declare @dateAdd int = 3 -- Add 3 month = 1 Quarter
    
    -- Get Current boundaries 
    Select @currentDate = DATEADD(MONTH, @dateAdd,Cast(MAX(value) as datetime2)) From sys.partition_range_values as r
        Inner Join sys.partition_functions as f on r.function_id = f.function_id
    Where f.name = 'RangePartFunction'
    
    -- Get all quarters between max and end date
    ; with d(id, date, name) as (
        Select 0, @currentDate, Convert(char(6), @currentDate, 112)
        Union All
        Select id+1, DATEADD(MONTH, @dateAdd, date), Convert(char(6), DATEADD(MONTH, @dateAdd, date), 112)
        From d Where d.date <= @endDate
    )
    Select * From (
        Select id = id*10, query = 'If Not Exists(Select 1 From sys.filegroups Where name = ''Part_'+name+''')
            Begin 
                Print ''Create Filegroup [Part_'+name+']''
                Alter Database [Test] Add Filegroup [Part_'+name+']
            End
            GO'
        From d
        Union All
        Select id*10+1, 'If Not Exists(Select 1 From sys.sysfiles Where name = ''Part_'+name+''')
            Begin 
                Print ''Create File [Part_'+name+'.ndf]''
                Alter Database [Test] Add FILE ( NAME = N''Part_'+name+''', FILENAME = N''C:\DB\MSSQL11.MSSQLSERVER\MSSQL\DATA\Part_'+name+'.ndf'' , SIZE = 5120KB , FILEGROWTH = 1024KB ) TO Filegroup [Part_'+name+']
            End
            GO'
        From d
        Union All
        Select id*10+2, 'Print ''Add Range [Part_'+name+']''
            Alter Partition Scheme RangePartScheme Next Used [Part_'+name+']
            Go'
        From d
        Union All
        Select id*10+3, 'Print ''Split Function ['+Convert(char(8), date, 112)+']''
            Alter Partition Function RangePartFunction() Split Range ('''+Convert(char(8), date, 112)+''');
            Go'
        From d
    ) as q order by id
    

la sortie de cette requête est une liste de requêtes SQL qui doivent être exécutées dans l'ordre.

Exécuter le SQL dynamique

  • Il peut être exécuté manuellement (copier et coller dans SSMS)
  • Il peut être exécuté dans une boucle while ou avec un curseur qui exécutera chaque ligne de la table de sortie une par une (utilisez sp_executesql)

Automatisation

  • Créez un travail SQL Server qui exécute les requêtes SQL: exécutez la requête utilisée pour créer le SQL dynamique, enregistrez sa sortie dans une variable de table, puis exécutez chaque instruction avec une boucle/curseur

Si vous souhaitez l'exécuter tous les mois et vous assurer que les 12 prochains mois sont toujours créés, utilisez cette Set @endDate = DATEADD(MONTH, 12, getdate())

Finalement

  • Il affichera 4 * N lignes pour les N trimestres manquants entre la dernière limite de la fonction et @endDate:

    • Créer un groupe de fichiers
    • Créer un fichier sur un groupe de fichiers
    • Étendre la portée du schéma de partition
    • Fractionner la plage de la fonction de partition
  • Vous pouvez l'exécuter ligne par ligne avec un curseur ou une boucle while ou vous pouvez simplement le copier et le coller dans SMSS.

  • Il peut également être automatisé avec un travail, c.-à-d. @endDate = DATEADD(MONTH, 3, getdate() créera les 3 prochains mois
  • Remplacez @dateAdd par 1 si vous souhaitez des partitions mensuelles
  • Ajoutez vos propres colonnes ou chèques

Lien

Créer un travail = https://www.mssqltips.com/sqlservertip/3052/simple-way-to-create-a-sql-server-job-using-tsql/

sp_executesql = https://technet.Microsoft.com/en-us/library/ms188001%28v=sql.110%29.aspx

Boucle while = https://dba.stackexchange.com/questions/57933/can-exec-work-with- while-loop-of-cursor

18
Julien Vavasseur