OMM創建分區表

sql server:

1:首先我們創建test1數據庫和shop表

2:創建文件組和文件

 3:創建分區

    ①:右鍵Shop表,彈出菜單中選擇 “存儲” => "創建分區"

 

  ②:創建“分區函數”名 和 “分區方案”名。

 

③:創建分區映射,也就是將”分區函數“和“文件組”進行關聯。

 

④:  最後我們可以看一下界面給我生成的分區函數以及分區方案,蠻有意思的。

複製代碼

 1 USE [Test1]
 2 GO
 3 BEGIN TRANSACTION
 4 CREATE PARTITION FUNCTION [MyRangeCreatTime](datetime) AS RANGE LEFT FOR VALUES (N'2012-12-31T00:00:00', N'2013-12-31T00:00:00', N'2014-12-31T00:00:00')
 5 
 6 
 7 CREATE PARTITION SCHEME [MySchemeCreateTime] AS PARTITION [MyRangeCreatTime] TO ([Before2013], [T2013], [T2014], [After2014])
 8 
 9 
10 ALTER TABLE [dbo].[Shop] DROP CONSTRAINT [PK__Shop__3214EC277F60ED59]
11 
12 
13 ALTER TABLE [dbo].[Shop] ADD PRIMARY KEY NONCLUSTERED 
14 (
15     [ID] ASC
16 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
17 
18 
19 CREATE CLUSTERED INDEX [ClusteredIndex_on_MySchemeCreateTime_635288828144372217] ON [dbo].[Shop] 
20 (
21     [CreateTime]
22 )WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [MySchemeCreateTime]([CreateTime])
23 
24 
25 DROP INDEX [ClusteredIndex_on_MySchemeCreateTime_635288828144372217] ON [dbo].[Shop] WITH ( ONLINE = OFF )
26 
27 
28 
29 
30 COMMIT TRANSACTION

複製代碼


從圖中可以看到生成好的分區函數名”[MyRangeCreatTime]“ 和分區架構名“[MySchemeCreateTime]”,最後我們執行下該sql就ok了。

 

⑤ 插入測試數據並進行簡單的測試

    這裏測試下“2013-1-1”是在哪個分區下。

 

 

總結一下可能用到的所有sql語句:

1,新建默認的 filegroup   
alter database Test add filegroup Before2013
2, 新建默認的 file   
alter database Test add file
(Name=N'Before2013',filename='D:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\Before20131.ndf',size=5mb,maxsize=100Mb,filegrowth=5mb) 
to filegroup Before2013
3,新建分區函數
create partition function RangeTime (datetime) as range left for values ('2012-12-31','2013-12-31','2014-12-31')
4,新建分區方案
 create partition scheme RangeSchema_CreateTime  as partition RangeTime to (before2013,T2013,T2014,after2014)
5,新建表
create table equipment_n
  (
[dataId] [int]  NOT NULL,
[operaDate] datetime NULL,
[eqId] [int] NULL,
[l1] [varchar](30) NULL,
[l2] [varchar](30) NULL,
[lc] [varchar](30) NULL,
  ) on RangeSchema_CreateTime(operaDate)
 
 6, 自動添加數據
  declare @i int
 set @i = 4
 
 while @i < 1000
 begin insert into equipment_n ([operaDate]
           ,[eqId]
           ,[l1]
           ,[l2]
           ,[lc]) values(dateadd(dd,datediff(dd,'2012-01-01','2015-01-30')*RAND(),'2012-01-01'),1,@i+1,@i+2,@i+3)
 set @i = @i +1
 end
 
 7,   查詢分區表中數據分佈情況
 select $partition.RangeTime(operaDate) as number, COUNT(*) as count
 from equipment_n group by $partition.RangeTime(operaDate)
 
 8, 設置自增ID
 alter table equipment_n drop column dataId alter table equipment_n add dataId int  identity(1,1)
 ALTER TABLE dbo.equipment_n ADD CONSTRAINT
PK_equipment_n  PRIMARY KEY NONCLUSTERED 
(
dataId 
) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]


9, 定製計劃
DECLARE @maxValue INT,
    @secondMaxValue INT,
    @differ    INT,
    @fileGroupName VARCHAR(200),
    @fileNamePath    VARCHAR(200),
    @fileName   VARCHAR(200),
    @sql        NVARCHAR(1000)


if(MONTH(GETDATE()) != '12')--計劃每月執行,如果是12月則可以更新分局
begin
--生成新的文件組
SET @fileGroupName='IN_'+ convert(varchar(4),(YEAR(GETDATE())+1))
PRINT @fileGroupName
SET @sql='ALTER DATABASE [iom_db] ADD FILEGROUP '+@fileGroupName
PRINT @sql
EXEC(@sql)

--新建文件
SET @fileNamePath='C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA'
+ @fileGroupName +'.NDF'
SET @fileName=N'File'+convert(varchar(4),(YEAR(GETDATE())+1)) 


SET @sql='ALTER DATABASE [iom_db] ADD FILE (NAME='''+@fileName+''',FILENAME=N'''+@fileNamePath+''') TO FILEGROUP'+'    '+@fileGroupName
PRINT @sql
PRINT 1 
EXEC(@sql)
PRINT 2 

--修改分區方案,用一個新的文件組用於存放下一新增的數據
SET @sql='ALTER PARTITION SCHEME [RangeSchema_CreateTime] NEXT USED'+'    '+@fileGroupName
EXEC(@sql)
PRINT 3 

ALTER PARTITION FUNCTION RangeTime()  --分區函數
SPLIT RANGE  (convert(datetime, convert(varchar(4),(YEAR(GETDATE())+1))+'-12-31 00:00:00.000'))
end

 

oracle:

首先明確分區表和表分區的區別:表分區是一種思想,分區表示一種技術實現。當表的大小過G的時候可以考慮進行表分區,提高查詢效率,均衡IO。oracle分區表是oracle數據庫提供的一種表分區的實現形式。表進行分區後,邏輯上仍然是一張表,原來的查詢SQL同樣生效,同時可以採用使用分區查詢來優化SQL查詢效率,不至於每次都掃描整個表


一、分區表基本操作
1、按時間分區表創建:
create table t_test (
   pk_id                number(30)                      not null,
  add_date_time        DATE,
   constraintPK_T_TEST primary key (pk_id)
)
PARTITION BY RANGE (add_date_time)
(
  PARTITIONt_test_2013_less VALUES LESS THAN (TO_DATE('2013-01-01 00:00:00','yyyy-mm-ddhh24:mi:ss')) TABLESPACE TS_MISPS,
  PARTITIONt_test_2013 VALUES LESS THAN (TO_DATE('2014-01-01 00:00:00','yyyy-mm-ddhh24:mi:ss')) TABLESPACE TS_MISPS,
  PARTITION t_test_2014VALUES LESS THAN (TO_DATE('2015-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss'))TABLESPACE TS_MISPS
)
其中add_date_time爲分區字段,每一年一個分區。

插入100W數據

declare
  i    int := 1;
  yearVARCHAR2(20);
begin
  loop
    year := CASEmod(i, 3)
             WHEN 0 THEN
              '2012-01-14 12:00:00'
             WHEN 1 THEN
              '2013-01-14 12:00:00'
             ELSE
              '2014-01-14 12:00:00'
            END;
           insert into t_test values(i, to_date(year, 'yyyy-mm-dd hh24:mi:ss'));
    exit when i= 1000000;
    i := i + 1;
  end loop;
end;
查看分區表的分區的詳細信息

Select table_name,partition_name,high_value fromdba_tab_partitions where table_name='T_TEST';
2、分區表修改
2.1增加一個分區
分兩種情況:1.沒有maxvalue分區。2.有maxvalue分區。我們創建的分區就是沒有maxValue的分區

1.沒有maxvalue分區添加新分區:

alter table t_test add partition t_test_2015 VALUESLESS THAN (TO_DATE('2015-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss')) TABLESPACETS_MISPS ;

2、有maxvalue分區添加新分區:

有了maxvalue,就不能直接add partition,而是需要max分區split。例如我們將創建的分區的語句修改下:

create table t_test (
   pk_id                number(30)                      not null,
  add_date_time        DATE,
   constraintPK_T_TEST primary key (pk_id)
)
PARTITION BY RANGE (add_date_time)
(
  PARTITIONt_test_2013_less VALUES LESS THAN (TO_DATE('2013-01-01 00:00:00','yyyy-mm-ddhh24:mi:ss')) TABLESPACE TS_MISPS,
  PARTITIONt_test_2013 VALUES LESS THAN (TO_DATE('2014-01-01 00:00:00','yyyy-mm-ddhh24:mi:ss')) TABLESPACE TS_MISPS,
  PARTITIONt_test_2014 VALUES LESS THAN (TO_DATE('2015-01-01 00:00:00','yyyy-mm-ddhh24:mi:ss')) TABLESPACE TS_MISPS,
    PARTITION t_test_maxVALUES LESS THAN (MAXVALUE)
)
增加一個2016年的分區語句爲:

alter table t_test split partition t_test_max at(TO_DATE('2016-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss')) into (partitiont_test_2015,partition t_test_max);
2.2刪除一個分區
alter table t_test drop partition t_test_2014

注:droppartition時,該分區內存儲的數據也將同時刪除,你的本意是希望刪除掉指定的分區但保留數據,你應該使用merge partition,執行該語句會導致glocal索引的失效需要重建全局索引

2.3合併分區
相鄰的分區可以merge爲一個分區,新分區的下邊界爲原來邊界值較低的分區,上邊界爲原來邊界值較高的分區,原先的局部索引相應也會合並,全局索引會失效,需要rebuild。

Alter  table t_test  merge partitions t_test_2013  ,t_Test_2014 into partition t_Test_2013_to_2014

二、對分區表進行查詢
2.1查詢
不使用分區查詢:默認查詢所有分區數據

select * from t_test

使用分區查詢:只查詢該分區數據

select * from t_testpartition(t_test_2014) where add_date_time >=TO_DATE('2014-01-01 00:00:00','yyyy-mm-dd hh24:mi:ss');
2.1插入
insert into t_test values(i, to_date(year,'yyyy-mm-dd hh24:mi:ss'));
2.1刪除
使用分區刪除

更新的時候指定了分區,而根據查詢的記錄不在該分區中時,將不會刪除數據

delete t_test partition(t_test_2013) where id=1;
不使用分區刪除

delete t_test  whereid=1;
2.1修改
使用分區更新

更新的時候指定了分區,而根據查詢的記錄不在該分區中時,將不會更新數據

delete t_test where id=1;
update t_test partition(t_test)  set id=1 where id=2;
不使用分區

delete t_test where id=1;
update t_test  set id=1 where id=2;
三、普通表和分區表互轉
普通表—>分區表

1、新建一個字段一樣的中間的分區表(T_NEW)

2、將T數據導入到T_NEW中

INSERT INTO T SELECT field1,filed2, …from T
將老表重命名

RENAME T TO T_OLD;
將新表重命名

RENAME T_NEW TO T;
這種適合靜態操作,不保證數據一致性。如果在生產環境切換,利用利用在線重定義功能

 

mysql:

CREATE TABLE p1 
    -> (    a INT,   
    ->  b INT,    
    ->  c INT )  
    ->  PARTITION BY RANGE COLUMNS (a) 
    ->   (    PARTITION p01 VALUES LESS THAN (10),  
    ->     PARTITION p02 VALUES LESS THAN (20),   
    ->      PARTITION p03 VALUES LESS THAN (30), 
    ->    PARTITION p04 VALUES LESS THAN (MAXVALUE)  ); 
--------------------- 

        Mysql的安裝方法可以參考:

        http://blog.csdn.net/jhq0113/article/details/43812895

        

        Mysql分區表的介紹可以參考:

        http://blog.csdn.net/jhq0113/article/details/44592865

       

       1.檢查你的Mysql是否支持分區

        mysql> SHOW VARIABLES LIKE '%partition%';

       若結果如下,表示你的Mysql支持表分區:

        +-----------------------+-------+

       | Variable_name         | Value |
       +-----------------------+-------+
       | have_partition_engine | YES   |
       +-----------------------+-------+
       1 row in set (0.00 sec)
       
               RANGE分區表創建方式:
DROP TABLE IF EXISTS `my_orders`;
CREATE TABLE `my_orders` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '表主鍵',
  `pid` int(10) unsigned NOT NULL COMMENT '產品ID',
  `price` decimal(15,2) NOT NULL COMMENT '單價',
  `num` int(11) NOT NULL COMMENT '購買數量',
  `uid` int(10) unsigned NOT NULL COMMENT '客戶ID',
  `atime` datetime NOT NULL COMMENT '下單時間',
  `utime` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '修改時間',
  `isdel` tinyint(4) NOT NULL DEFAULT '0' COMMENT '軟刪除標識',
  PRIMARY KEY (`id`,`atime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
 
/*********分區信息**************/
PARTITION BY RANGE (YEAR(atime))
(
   PARTITION p0 VALUES LESS THAN (2016),
   PARTITION p1 VALUES LESS THAN (2017),
   PARTITION p2 VALUES LESS THAN MAXVALUE
);
        以上是一個簡單的訂單表,分區字段是atime,根據RANGE分區,這樣當你向該表中插入數據的時候,Mysql會根據YEAR(atime)的值進行分區存儲。


        檢查分區是否創建成功,執行查詢語句:

         EXPLAIN PARTITIONS SELECT * FROM `my_orders`

         若成功,結果如下:

        

         

        性能分析:

        1).創建同樣表結構,但沒有進行分區的表     

DROP TABLE IF EXISTS `my_order`;
CREATE TABLE `my_order` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '表主鍵',
  `pid` int(10) unsigned NOT NULL COMMENT '產品ID',
  `price` decimal(15,2) NOT NULL COMMENT '單價',
  `num` int(11) NOT NULL COMMENT '購買數量',
  `uid` int(10) unsigned NOT NULL COMMENT '客戶ID',
  `atime` datetime NOT NULL COMMENT '下單時間',
  `utime` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '修改時間',
  `isdel` tinyint(4) NOT NULL DEFAULT '0' COMMENT '軟刪除標識',
  PRIMARY KEY (`id`,`atime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
        2).向兩張表中插入相同的數據

      

/**************************向分區表插入數據****************************/
INSERT INTO my_orders(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89757,CURRENT_TIMESTAMP());
INSERT INTO my_orders(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89757,'2016-05-01 00:00:00');
INSERT INTO my_orders(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89757,'2017-05-01 00:00:00');
INSERT INTO my_orders(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89757,'2018-05-01 00:00:00');
INSERT INTO my_orders(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89756,'2015-05-01 00:00:00');
INSERT INTO my_orders(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89756,'2016-05-01 00:00:00');
INSERT INTO my_orders(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89756,'2017-05-01 00:00:00');
INSERT INTO my_orders(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89756,'2018-05-01 00:00:00');
 
/**************************向未分區表插入數據****************************/
INSERT INTO my_order(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89757,CURRENT_TIMESTAMP());
INSERT INTO my_order(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89757,'2016-05-01 00:00:00');
INSERT INTO my_order(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89757,'2017-05-01 00:00:00');
INSERT INTO my_order(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89757,'2018-05-01 00:00:00');
INSERT INTO my_order(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89756,'2015-05-01 00:00:00');
INSERT INTO my_order(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89756,'2016-05-01 00:00:00');
INSERT INTO my_order(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89756,'2017-05-01 00:00:00');
INSERT INTO my_order(`pid`,`price`,`num`,`uid`,`atime`) VALUES(1,12.23,1,89756,'2018-05-01 00:00:00');

        3).主從複製,大約20萬條左右(主從複製的數據和真實環境有差距,但是能體現出表分區查詢的性能優劣)
        

/**********************************主從複製大量數據******************************/
INSERT INTO `my_orders`(`pid`,`price`,`num`,`uid`,`atime`) SELECT `pid`,`price`,`num`,`uid`,`atime` FROM `my_orders`;
INSERT INTO `my_order`(`pid`,`price`,`num`,`uid`,`atime`) SELECT `pid`,`price`,`num`,`uid`,`atime` FROM `my_order`;
     
       4).查詢測試 

/***************************查詢性能分析**************************************/
SELECT * FROM `my_orders` WHERE `uid`=89757 AND `atime`< CURRENT_TIMESTAMP();
/****用時0.084s****/
 
SELECT * FROM `my_order` WHERE `uid`=89757 AND `atime`< CURRENT_TIMESTAMP();
/****用時0.284s****/

      通過以上查詢可以明顯看出進行表分區的查詢性能更好,查詢所花費的時間更短。
      分析查詢過程:

      EXPLAIN PARTITIONS SELECT * FROM `my_orders` WHERE `uid`=89757 AND `atime`< CURRENT_TIMESTAMP();

            

      EXPLAIN PARTITIONS SELECT * FROM `my_order` WHERE `uid`=89757 AND `atime`< CURRENT_TIMESTAMP();

            

       通過以上結果可以看出,my_orders表查詢直接經過p0分區,只掃描了49386行,而my_order表沒有進行分區,掃描了196983行,這也是性能得到提升的關鍵所在。

       當然,表的分區並不是分的越多越好,當表的分區太多時找分區又是一個性能的瓶頸了,建議在200個分區以內。

      LIST分區表創建方式:

      

/*****************創建分區表*********************/
CREATE TABLE `products` (
`id`  bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '表主鍵' ,
`name`  varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '產品名稱' ,
`metrial`  tinyint UNSIGNED NOT NULL COMMENT '材質' ,
`weight`  double UNSIGNED NOT NULL DEFAULT 0 COMMENT '重量' ,
`vol`  double UNSIGNED NOT NULL DEFAULT 0 COMMENT '容積' ,
`c_id`  tinyint UNSIGNED NOT NULL COMMENT '供貨公司ID' ,
PRIMARY KEY (`id`,`c_id`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8
 
/*********分區信息**************/
PARTITION BY LIST(c_id)
(
    PARTITION pA VALUES IN (1,3,11,13),
    PARTITION pB VALUES IN (2,4,12,14),
    PARTITION pC VALUES IN (5,7,15,17),
    PARTITION pD VALUES IN (6,8,16,18),
    PARTITION pE VALUES IN (9,10,19,20)
);

 

       可以看出,LIST分區和RANGE分區很類似,這裏就不做性能分析了,和RANGE很類似。
       HASH分區表的創建方式:

 

/*****************分區表*****************/
CREATE TABLE `msgs` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '表主鍵',
  `sender` int(10) unsigned NOT NULL COMMENT '發送者ID',
  `reciver` int(10) unsigned NOT NULL COMMENT '接收者ID',
  `msg_type` tinyint(3) unsigned NOT NULL COMMENT '消息類型',
  `msg` varchar(225) NOT NULL COMMENT '消息內容',
  `atime` int(10) unsigned NOT NULL COMMENT '發送時間',
  `sub_id` tinyint(3) unsigned NOT NULL COMMENT '部門ID',
  PRIMARY KEY (`id`,`sub_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*********分區信息**************/
PARTITION BY HASH(sub_id)
PARTITIONS 10;

          以上語句代表,msgs表按照sub_id進行HASH分區,一共分了十個區。

       Key分區和HASH分區很類似,不再介紹,若想了解可以參考Mysql官方文檔進行詳細瞭解。

       子分區的創建方式:

      

CREATE TABLE `msgss` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '表主鍵',
  `sender` int(10) unsigned NOT NULL COMMENT '發送者ID',
  `reciver` int(10) unsigned NOT NULL COMMENT '接收者ID',
  `msg_type` tinyint(3) unsigned NOT NULL COMMENT '消息類型',
  `msg` varchar(225) NOT NULL COMMENT '消息內容',
  `atime` int(10) unsigned NOT NULL COMMENT '發送時間',
  `sub_id` tinyint(3) unsigned NOT NULL COMMENT '部門ID',
  PRIMARY KEY (`id`,`atime`,`sub_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*********分區信息**************/
PARTITION BY RANGE (atime) SUBPARTITION BY HASH (sub_id) 
(
        PARTITION t0 VALUES LESS THAN(1451577600)
        (
            SUBPARTITION s0,
            SUBPARTITION s1,
            SUBPARTITION s2,
            SUBPARTITION s3,
            SUBPARTITION s4,
            SUBPARTITION s5
        ),
        PARTITION t1 VALUES LESS THAN(1483200000)
        (
            SUBPARTITION s6,
            SUBPARTITION s7,
            SUBPARTITION s8,
            SUBPARTITION s9,
            SUBPARTITION s10,
            SUBPARTITION s11
        ),
        PARTITION t2 VALUES LESS THAN MAXVALUE
        (
            SUBPARTITION s12,
            SUBPARTITION s13,
            SUBPARTITION s14,
            SUBPARTITION s15,
            SUBPARTITION s16,
            SUBPARTITION s17
        )
);

         檢查子分區是否創建成功:
        EXPLAIN PARTITIONS SELECT * FROM msgss;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章