【问题标题】:How to Partition a Table by Month ("Both" YEAR & MONTH) and create monthly partitions automatically?如何按月(“年”和“月”)对表进行分区并自动创建月度分区?
【发布时间】:2015-11-02 15:09:41
【问题描述】:

我正在尝试按 YearMonth 对表进行分区。我将通过其进行分区的列是具有 ISO 格式('20150110'、20150202'等)的日期时间类型列。

例如,我有 2010 年、2011 年、2012 年的销售数据。我希望数据按年分区,并且每年也按月分区。 (2010/01, 2010/02, ... 2010/12, 2011/01, ... 2015/01...)

E.X:

Sales2010Jan、Sales2010Feb、Sales2011Jan、Sales2011Feb、Sales2012Dec 等

我的问题是:这甚至可能吗?如果是,我如何使用 SSIS 自动化流程?

【问题讨论】:

  • 您是在物理上将数据分区到多个表中以准备在partitioned view 中使用,还是尝试实现表分区的企业版功能?
  • 或者您只是想根据您的分区数据显示动态 PIVOT 列?
  • 你应该使用日期时间,而不是字符串,然后按每个周期的第一天进行分区。
  • @billinkc 我正在尝试使用 SQL 企业版对它们进行分区...但是,我不知道是否可以根据 2 个标准进行分区。正如问题中提到的,我的主要目标是能够将每个月保存在自己的分区文件中,例如 Sales2010Jan、Sales2010Feb、Sales2011Jan、Sales2011Feb、Sales2012Dec 等......
  • @FutbolFan 我正在尝试使用 SQL 企业版对它们进行分区...但是,我不知道是否可以根据 2 个标准进行分区。正如问题中提到的,我的主要目标是能够将每个月保存在自己的分区文件中,例如 Sales2010Jan、Sales2010Feb、Sales2011Jan、Sales2011Feb、Sales2012Dec 等......

标签: sql sql-server partitioning dynamic-sql sql-agent-job


【解决方案1】:

SSIS 是一个 ETL(提取、转换、加载)。这不是你想要做的。 您只需要动态创建 DDL 语句。

我使用以下季度,但如果您愿意,它也适用于 1、2 或 X 个月。

如果要对表进行分区,首先需要创建文件、文件组和分区表并手动设置分区

在具有 int 标识 PK 和 datetime2 分区列的表上为 2015 Q1(之前、Q1 和 Q2 之后)创建 N+1 个分区。 更新它以添加几个月,每月或任何你需要的......

  • 先创建N个文件组:

    Alter Database [Test] Add Filegroup [Part_Before2015]
    Go
    Alter Database Test Add Filegroup [Part_201501]
    Go
    Alter Database Test Add Filegroup [Part_201504]
    Go
    
  • 为每个文件组添加一个文件:

    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]
    
  • 在 datetime2 类型(或日期甚至日期时间)上创建分区函数:

    Create Partition Function RangePartFunction (datetime2)
    as Range Right For Values ('20150101', '20150401') 
    
  • 在每个文件组(N+1)上使用分区函数创建分区方案:

    Create Partition Scheme RangePartScheme as Partition RangePartFunction
    To ([Part_Before2015], [Part_201501], [Part_201504])
    
  • 在其分区方案上创建分区表:

    Create TABLE [PartitionTable] (id int identity(0, 1) not null, date datetime2 not null, text char(8000))
    On RangePartScheme (date) ;
    
  • 在分区列和分区方案上添加聚集索引:

    Create Clustered Index IDX_Part On dbo.PartitionTable(date) 
        On RangePartScheme (date);
    
  • 在 id 列中添加 PK:

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

构建用于在右边界之后添加额外文件组并拆分最后一个分区的查询

  • 查看分区方案扩展和分区函数拆分
  • 查看使用的 DMV
  • 查看所有这些以及如何使用它来创建动态 SQL

    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
    

此查询的输出是必须按顺序运行的 SQL 查询列表。

执行动态SQL

  • 可以手动执行(在SSMS中复制粘贴)
  • 它可以在 while 循环中执行,也可以使用游标执行,游标将一一执行输出表的每一行(使用 sp_executesql)

自动化

  • 创建执行 SQL 查询的 SQL Server 作业:运行用于创建动态 SQL 的查询,将其输出保存到表变量中,然后使用循环/游标执行每个语句

如果您想每月运行它并确保始终创建接下来的 12 个月,请使用此Set @endDate = DATEADD(MONTH, 12, getdate())

终于

  • 它将为函数的最后一个边界和@endDate之间的N个缺失季度输出4*N行:

    • 创建文件组
    • 在文件组上创建文件
    • 扩展分区方案的范围
    • 分割分区函数的范围
  • 您可以使用游标或 while 循环逐行运行它,也可以将其复制并粘贴到 SMSS 中。

  • 它也可以通过作业自动化,即。 @endDate = DATEADD(MONTH, 3, getdate() 将创造未来 3 个月
  • 如果需要每月分区,请将 @dateAdd 更改为 1
  • 添加您自己的列或检查

链接

创建工作 = 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

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

【讨论】:

  • 有没有一种可能的方法来创建一个自动化的 SSIS 维护包,它将根据日期不断更新分区?这意味着例如,如果它每年运行,那么它将为新的一年及其月份创建分区..
  • Sql server 可以自动执行包含 SQL 或 SSIS 包的任务。在这种情况下,你有 sql。无需使用 SSIS 包。如果您运行此脚本并将开头的固定日期替换为 get date + 12 或 13 个月。它会完成这项工作。您需要添加一个循环,该循环将执行最后一次选择的每个语句。我在答案的最后解释了这一切。一切都使用 SQL 完成。
  • 请原谅,因为我不是专家,但我对这一切还是很陌生 :) 我理解你到目前为止所写的所有内容的概念,并为此感谢你。但是,当我运行它时,我没有得到的是查询的最后一部分(- 获取最大日期和结束日期之间的所有季度),它不会在两个日期之间创建任何文件组。只是打印查询..这是什么目的?再次抱歉
  • 非常感谢您的详细解释 :) 我会正确了解已编辑的解决方案,并让您知道它是如何进行的 :)
  • 我因病假而耽误了时间,我深表歉意。无论如何,非常感谢您的努力,它工作得很好:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 2019-10-01
  • 2020-04-15
相关资源
最近更新 更多