如何对一个已经存在的SQL Server表分区

如何对一个已经存在的SQL Server表分区,第1张

有两种方法可以实现对一个表分区一是创建一个新的标识为分区表的表(你可参照此步骤),然后把数据复制到这张新表,再对这两张表分别改名或者,像我写在下面的,通过重建或创建一个聚集索引来达到分区一个表
一个SQL Server表和数据进行分区示例
--Table/Index creation
CREATE TABLE [dbo][TABLE1]
([pkcol] [int] NOT NULL,
[datacol1] [int] NULL,
[datacol2] [int] NULL,
[datacol3] [varchar](50) NULL,
[partitioncol] datetime)
GO
ALTER TABLE dboTABLE1 ADD CONSTRAINT PK_TABLE1 PRIMARY KEY CLUSTERED (pkcol)
GO
CREATE NONCLUSTERED INDEX IX_TABLE1_col2col3 ON dboTABLE1 (datacol1,datacol2)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]

  表分区是将⼀个表的数据按照⼀定的规则⽔平划分为不同的逻辑块,并分别进⾏物理存储,这个规则就叫做分区函数,可以有不同的分区规则。57可以通过show plugins语句查看当前MySQL是否⽀持表分区功能。

  但当表中含有主键或唯⼀键时,则每个被⽤作 分区函数的字段必须是表中唯⼀键和主键的全部或⼀部分 ,否则就⽆法创建分区表。⽐如下⾯的表由于唯⼀键和主键没有相同的字段,所以⽆法创建表分区

上述例⼦中删除唯⼀键,确保主键中的字段包含分区函数中的所有字段,创建成功

或者将主键扩展为包含ref字段

表分区的主要优势在于:
  可以允许在⼀个表⾥存储更多的数据,突破磁盘限制或者⽂件系统限制
  对于从表⾥将过期或历史的数据移除在表分区很容易实现,只要将对应的分区移除即可
  对某些查询和修改语句来说,可以 ⾃动 将数据范围缩⼩到⼀个或⼏个表分区上,优化语句执⾏效率。⽽且可以通过 显示指定表分区 来执⾏语句,⽐如 SELECT FROM t PARTITION (p0,p1) WHERE c < 5

表分区类型分为:


范围表分区,按照⼀定的范围值来确定每个分区包含的数据,分区函数使⽤的字段必须只能是 整数类型,分区的定义范围必须是连续的,且不能有重叠部分,通过使⽤VALUES LESS THAN来定义分区范围,表分区的范围定义是从⼩到⼤定义的

⽐如:

  Store_id<6的数据被放在p0分区⾥,6<=store_id<10之间的数据被放在p1分区⾥,以此类推,当新插⼊的数据为(72, ‘Mitchell’, ‘Wilson’, ‘1998-06-25’, NULL, 13) 时,则新数据被插⼊到p2分区⾥,但当插⼊的数据的store_id为21时,由于没有分区去容纳此数据,所以会报错,我们需要修改⼀下表的定义
报错:

修改表的定义:

   MAXVALUE关键词的作⽤是表示可能的最⼤值,所以任何store_id>=16的数据都会被写⼊到p3分区⾥。分区函数中也可以使⽤表达式 ,⽐如:

   对timestamp字段类型可以使⽤的表达式⽬前仅有unix_timestamp ,其他的表达式都不允许


列表表分区,按照⼀个⼀个确定的值来确定每个分区包含的数据,通过PARTITION BY LIST(expr)分区函数表达式必须返回整数,取值范围通过VALUES IN (value_list)定义

对List表分区来说,没有MAXVALUE特殊值,所有的可能取值都需要再VALUES IN中包含,如果有未定义的取值则会报错

同样,当有主键或者唯⼀键存在的情况下,分区函数字段需要包含在主键或唯⼀键中

对range和list表分区来说,分区函数可以包含多个字段,分区多字段函数(column partition) 所涉及的字段类型可以包括:

范围多字段分区函数与普通的范围分区函数的区别在于:
a) 字段类型多样化
b) 范围多字段分区函数 不⽀持表达式,只能⽤字段名
c) 范围多字段分区函数⽀持⼀个或多个字段

再⽐如创建如下的表分区:

对多列对⽐来说:

当然只要保证取值范围是增⻓的,表分区就能创建成功,⽐如:

但如果 取值范围不是增⻓的,就会返回错误

对其他数据类型的⽀持:

list列表多字段表分区,例如:你有一个在12个城市客户的业务, 为了销售和市场的目的, 你的组织每3个城市划分为一个区域针对LIST COLUMNS分区, 你可以基于城市的名称创建一个客户数据表并声明4个分区当你的客户在对应的这个区域:

使用日期分区

但是这种情况在日期增长到非常大的时候是很复杂的, 所以这种还是使用RANGE 分区方式比较好


  按照⼀个⾃定义的函数返回值来确定每个分区包含的数据,这个 ⾃定义函数也可以仅仅是⼀个字段名字
  通过PARTITION BY HASH (expr)⼦句来表达哈希表分区,其中的 expr表达式必须返回⼀个整数,基于分区个数的取模(%)运算。根据余数插⼊到指定的分区
  对哈希表分区来说只需要定义分区的个数,其他的事情由内部完成

如果没有写明PARTITIONS字段,则默认为1,表达式可以是整数类型字段,也可以是⼀个函数,⽐如

⽐如: CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY HASH( YEAR(col3) ) PARTITIONS 4;
如果插⼊⼀条数据对应的col3为‘2005-09-15’时,则插⼊数据的分区计算⽅法为:


  与哈希表分区类似,只不过哈希表分区依赖于⾃定义的函数,⽽key表分区的哈希算法是依赖MySQL本身, CREATE TABLE PARTITION BY KEY () 创建key表分区, 括号⾥⾯可以包含0个或者多个字段,所引⽤的字段必须是主键或者主键的⼀部分 ,如果括号⾥⾯没有字段,则代表使⽤主键

如果表中没有主键但有唯⼀键,则使⽤唯⼀键,但 唯⼀键字段必须定义为not null ,否则报错

所引⽤的字段未必必须是整数类型,其他的类型也可以使⽤,⽐如:

⼦表分区,是在表分区的基础上再创建表分区的概念, 每个表分区下的⼦表分区个数必须⼀致 ,⽐如:

ts表拥有三个范围分区,同时每个分区都各⾃有两个⼦分区,所以总共有6个分区

⼦表分区必须是范围/列表分区+哈希/key⼦表分区的组合
⼦表分区也可以显示的指定⼦表分区的名字,⽐如:

不同的表分区对NULL值的处理⽅式不同
对范围表分区来说,如果插⼊的是NULL值,则将数据放到最⼩的分区表⾥

对list表分区来说,⽀持NULL值的唯⼀情况就是某个分区的允许值中包含NULL

对哈希表分区和Key表分区来说,NULL值会被当成0值对待

通过alter table命令可以执⾏增加,删除,重新定义,合并或者拆分表分区的管理动作
对范围表分区和列表表分区来说,删除⼀个表分区命令如下:

删除表分区的动作不光会把分区删掉,也会把表分区⾥原来的数据给删除掉

在原分区上增加⼀个表分区可以通过alter table … add partition语句来完成

但对范围表分区来说,增加的表分区必须在尾部增加,在头部或者在中间增加都会失败:

为解决这个问题,可以使⽤ REORGANIZE 命令:

对列表表分区来说,只要新增加的分区对应的值在之前的表分区中没有出现过,就可以通过alter table… add partition来增加

当然, 也可以通过REORGANIZE命令将之前的多个分区合并成⼀个或⼏个分区,但要保持分区值⼀致:

更复杂的⽐如将多个分区重组成多个分区:

1、一般分区表都会很大,所以可以先创建表空间,为了让分区表存放到单独的表空间,否则默认会存放到USERS表空间
2、创建TABLESPACE TS1:
CREATE TABLESPACE TS1 DATAFILE '/data1/oracle/testdbf' SIZE 512M AUTOEXTEND ON NEXT 512M MAXSIZE UNLIMITED;
3、创建分区表,需要确定按什么分区,比如按id或按时间段:
CREATE TABLE test_201602
(
ID NUMBER(10) NOT NULL,
CREATE_TIME DATE,
)
TABLESPACE TS1
PARTITION BY LIST (ID)
(PARTITION PT_1001 VALUES (1001) TABLESPACE TS1);
4、继续增加分区
ALTER TABLE test_201602 ADD PARTITION "PT_1003" VALUES (1003) LOGGING NOCOMPRESS;
ALTER TABLE test_201602 ADD PARTITION "PT_1004" VALUES (1004) LOGGING NOCOMPRESS;
5、查询表及分区数量
select TABLE_NAME,PARTITION_COUNT,DEF_TABLESPACE_NAME from USER_PART_TABLES order by DEF_TABLESPACE_NAME;

我们有一批日志数据存储在hdfs上,按天创建目录,如2018-07-31的日志hdfs路径为:/data/logs/gateway/20180731。
现在要用hive分析数据,同时要保证这些数据目录不能改变,就需要hive用外表的方式与这些数据进行关联。

示例:

但是,看下文件列表

一共108个待添加的目录,这样一个个添加太累人,有没有批量添加的方法呢?

Hive有个MSCK命令,可以扫描数据分区目录,修复元信息,目录与元信息不一致时,能自动更新。

但是,数据目录必须是Hive习惯路径格式:

同时,建表时指定LOCATION为分区目录的父目录:

这时,用命令

即可自动把所有的数据按dt分区,添加到gateway_analysis中。

由于我们的目录格式不符合,只能用ADD PARTITION的方式了。

为减少工作量,写了个shell脚本,自动添加 /data/logs/gateway 目录下所有的分区目录到gateway_analysis表中:

CREATE TABLE TABLE_NAME (COL1 VARCHAR2(20),
COL2 NUMBER,
COL3 DATE,
COL4 FLOAT,
COL5 CLOB ,
CONSTRAINT PK_NAME UNIQUE PRIMARY KEY ("COL1") --声明主键,这点非常重要
)
PARTITION BY RANGE(COL3) --分区字段
INTERVAL ( NUMTOYMINTERVAL(1,'MONTH')) --分区间隔,按月分区
(
PARTITION p1 VALUES LESS THAN (TO_DATE('2017-06-01','YYYY-MM-DD')) -- 设定第一个分区
)
ROWDEPENDENCIES --定义SCN行级依赖

CREATE TABLE TABLE_NAME
PARTITION BY RANGE(COL3) --分区字段
INTERVAL(NUMTOYMINTERVAL(1,'MONTH')) --定义分区时间间隔

PARTITION p1 VALUES LESS THAN(TO_DATE('2017-06-01','YYYY-MM-DD')) --定义第一个分区

ROWDEPENDENCIES NOLOGGING --定义SCN行级依赖
AS
SELECT FROM TABLE_NAME2

这种方式只是复制了源表的表结构,源表的索引、主键并没有复制过来,所以建好表之后要及时手动创建主键和索引,否则表的IO性能(UPDATE,INSERT)会非常非常糟糕。

主键:
ALTER TABLE TABLE_NAME2 ADD CONSTRAINT PK_NAME PRIMARY KEY ("COL1") NOLOGGING ;

索引:
CREATE INDEX IDX_NAME ON TABLE_NAME2(COL2) ONLINE NOLOGGING;

1、一般分区表都会很大,所以可以先创建表空间,为了让分区表存放到单独的表空间,否则默认会存放到USERS表空间
2、创建TABLESPACE TS1:
CREATE TABLESPACE TS1 DATAFILE '/data1/oracle/testdbf' SIZE 512M AUTOEXTEND ON NEXT 512M MAXSIZE UNLIMITED;
3、创建分区表,需要确定按什么分区,比如按id或按时间段:
CREATE TABLE test_201602
(
ID NUMBER(10) NOT NULL,
CREATE_TIME DATE,
)
TABLESPACE TS1
PARTITION BY LIST (ID)
(PARTITION PT_1001 VALUES (1001) TABLESPACE TS1);
4、继续增加分区
ALTER TABLE test_201602 ADD PARTITION "PT_1003" VALUES (1003) LOGGING NOCOMPRESS;
ALTER TABLE test_201602 ADD PARTITION "PT_1004" VALUES (1004) LOGGING NOCOMPRESS;
5、查询表及分区数量
select TABLE_NAME,PARTITION_COUNT,DEF_TABLESPACE_NAME from USER_PART_TABLES order by DEF_TABLESPACE_NAME;

--增加分区表的分区
ALTER TABLE AA ADD PARTITION SYS_P421 VALUES LESS THAN(TO_DATE('2017-05-21 00:00:00','YYYY-MM-DD HH24:MI:SS')) TABLESPACE USERS;

1、创建语句
create table p(id number)
partition by range(id)
(partition p1 values less than(100) tablespace t1,
partition p2 values less than(200) tablespace t2,
partition p3 values less than(300) tablespace t3);
2、添加分区
alter table p add partition p4 values less than (400) tablespace t4;
3、清除分区数据
alter table p trunc partition p1;
4、删除分区
alter table p drop partition p1;


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/13337414.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-07-17
下一篇 2023-07-17

发表评论

登录后才能评论

评论列表(0条)

保存