AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 224636
Accepted
user3657339
user3657339
Asked: 2018-12-12 01:42:07 +0800 CST2018-12-12 01:42:07 +0800 CST 2018-12-12 01:42:07 +0800 CST

按年对 SQL Server 表进行分区,滚动周期为 35 天

  • 772

我们正在尝试按年份(2015、2016、2017、2018)对 SQL Server 表进行分区,并且我们希望再创建一个分区来始终保存当前 35 天的周期数据。

分区:Part_2015、Part_2016、Part_2017、Part_2018、Part_35Day

Create Partition Function RangePartFunction (datetime2)
as Range Right For Values ('20150101', '20160101', '20170101') 

我正在努力我们如何为 2018 年和 35 天滚动期创建

谁能给点建议...

sql-server
  • 1 1 个回答
  • 2051 Views

1 个回答

  • Voted
  1. Best Answer
    Dan Guzman
    2018-12-12T07:16:06+08:002018-12-12T07:16:06+08:00

    SQL Server 当前无法以声明方式指定滑动分区窗口。需要执行 T-SQL 删除旧边界并创建新边界。为此,可以每天安排一个 T-SQL 脚本(可能封装在存储过程中)。

    通常最好只拆分和合并空分区,但在您的情况下这是不可能的,因为除了同一张表中的 35 天窗口分区之外,还有历史年度分区。以相对效率完成此任务的一种方法是使用相同的分区方案、函数和登台表。SPLIT这使您可以在 35 天窗口分区上进行操作,而无需MERGE进行非空分区所需的过多数据移动和日志记录。

    下面的脚本滑动每日窗口并使用DELETE...OUTPUT(每天 100K 行)将数据移动到活动窗口之外。活动窗口(大约 350 万行)中的数据的繁重工作是使用CREATE INDEX...WITH(DROP_EXISTING=ON). 我希望它在您的 3 小时维护窗口内运行良好,最坏的情况可能是几秒钟或几分钟。

    这假设您的表和索引是对齐的。下面是示例 DDL。

    CREATE PARTITION FUNCTION RangePartFunction (datetime2)
        AS RANGE RIGHT FOR VALUES ('20150101', '20160101', '20170101', '20180101'); 
    CREATE PARTITION FUNCTION RangePartFunction_Staging (datetime2)
        AS RANGE RIGHT FOR VALUES ('20150101', '20160101', '20170101', '20180101');
    CREATE PARTITION SCHEME RangePartScheme
        AS PARTITION RangePartFunction TO ([PRIMARY], Part_2015, Part_2016, Part_2017, Part_2018);
    CREATE PARTITION SCHEME RangePartScheme_Staging
        AS PARTITION RangePartFunction_Staging TO ([PRIMARY], Part_2015, Part_2016, Part_2017, Part_2018);
    
    --partition for last 35 days
    DECLARE @Start35DayWindowDate datetime2 = CAST(DATEADD(day, -35, CAST(SYSDATETIME() AS date)) AS datetime2);
    ALTER PARTITION SCHEME RangePartScheme
        NEXT USED Part_35Day;
    ALTER PARTITION SCHEME RangePartScheme_Staging
        NEXT USED Part_35Day;
    ALTER PARTITION FUNCTION RangePartFunction()
        SPLIT RANGE(@Date);
    ALTER PARTITION FUNCTION RangePartFunction_Staging()
        SPLIT RANGE(@Date);
    GO
    --example tables
    CREATE TABLE dbo.Table1(
          Col1 datetime2
        , Col2 int
        , Col3 char(1000) 
    ) ON RangePartScheme(Col1);
    CREATE CLUSTERED INDEX cdx ON dbo.Table1(Col2, Col1)  ON RangePartScheme(Col1);
    CREATE NONCLUSTERED INDEX idx ON dbo.Table1(Col2) ON RangePartScheme(Col1);
    CREATE TABLE dbo.Table1_Staging(
          Col1 datetime2
        , Col2 int
        , Col3 char(1000) 
    ) ON RangePartScheme(Col1);
    CREATE CLUSTERED INDEX cdx ON dbo.Table1_Staging(Col2, Col1)  ON RangePartScheme_Staging(Col1);
    CREATE NONCLUSTERED INDEX idx ON dbo.Table1_Staging(Col2) ON RangePartScheme_Staging(Col1);
    GO
    

    每日分区维护脚本(见内联注释):

    SET XACT_ABORT ON;
    BEGIN TRY
        BEGIN TRAN;
    
        DECLARE @Start35DayWindowDate datetime2  = CAST(DATEADD(day, -35, CAST(SYSDATETIME() AS date)) AS datetime2);
        DECLARE @LastBoundaryDate datetime2 = (
            SELECT MAX(CAST(value AS datetime2))
                FROM  sys.partition_functions AS pf
                JOIN sys.partition_range_values AS prv ON prv.function_id = pf.function_id
                WHERE 
                    pf.name =   N'RangePartFunction'
            );
    
        IF @Start35DayWindowDate > @LastBoundaryDate
        BEGIN
    
            --switch last partition into staging table
            ALTER TABLE dbo.Table1
                SWITCH PARTITION $Partition.RangePartFunction(@LastBoundaryDate)
                TO dbo.Table1_Staging PARTITION $Partition.RangePartFunction_Staging(@LastBoundaryDate);
            --merge original function (with empty partition)
            ALTER PARTITION FUNCTION RangePartFunction()
                MERGE RANGE(@LastBoundaryDate);
    
            --create new yearly partition when the 35-day window passes the first of the year
            --NOTE: current year filegroup must be created and this script changed with the new filegroup name before February 6th of each year
            IF @LastBoundaryDate = DATEADD(year, DATEDIFF(year, '', @LastBoundaryDate), '')
            BEGIN
                ALTER PARTITION SCHEME RangePartScheme
                    NEXT USED Part_2019;
                ALTER PARTITION FUNCTION RangePartFunction()
                    SPLIT RANGE(@LastBoundaryDate);
            END;
    
            --split original function for new 35-day window boundary
            ALTER PARTITION SCHEME RangePartScheme
                NEXT USED Part_35Day;
            ALTER PARTITION FUNCTION RangePartFunction()
                SPLIT RANGE(@Start35DayWindowDate);
    
            --rebuild staging table using original scheme
            CREATE CLUSTERED INDEX cdx ON dbo.Table1_Staging(Col2, Col1) WITH(DROP_EXISTING=ON) ON RangePartScheme(Col1);
            CREATE NONCLUSTERED INDEX idx ON dbo.Table1_Staging(Col2) WITH(DROP_EXISTING=ON) ON RangePartScheme(Col1);
    
            --switch partition with new window from staging table back into original table
            ALTER TABLE dbo.Table1_Staging
                SWITCH PARTITION $Partition.RangePartFunction(@Start35DayWindowDate)
                TO dbo.Table1 PARTITION $Partition.RangePartFunction(@Start35DayWindowDate);
    
            --move remaining rows into original table historical yearly file group (single day older than 35 days)
            DELETE dbo.Table1_Staging
                OUTPUT deleted.* INTO dbo.Table1;
    
            --apply same changes to staging function, scheme, and table to prepare for next day
            ALTER PARTITION FUNCTION RangePartFunction_Staging()
                MERGE RANGE(@LastBoundaryDate);
            ALTER PARTITION SCHEME RangePartScheme_Staging
                NEXT USED Part_35Day;
            ALTER PARTITION FUNCTION RangePartFunction_Staging()
                SPLIT RANGE(@Start35DayWindowDate);
            IF @LastBoundaryDate = DATEADD(year, DATEDIFF(year, '', @LastBoundaryDate), '')
            BEGIN
                ALTER PARTITION SCHEME RangePartScheme_Staging
                    NEXT USED Part_2019;
                ALTER PARTITION FUNCTION RangePartFunction_Staging()
                    SPLIT RANGE(@LastBoundaryDate);
            END;
            CREATE CLUSTERED INDEX cdx ON dbo.Table1_Staging(Col2, Col1) WITH(DROP_EXISTING=ON) ON RangePartScheme_Staging(Col1);
            CREATE NONCLUSTERED INDEX idx ON dbo.Table1_Staging(Col2) WITH(DROP_EXISTING=ON) ON RangePartScheme_Staging(Col1);
        END;
        COMMIT;
    END TRY
    BEGIN CATCH
        IF @@TRANCOUNT > 0 ROLLBACK;
        THROW;
    END CATCH;
    GO
    
    • 2

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve