轉移資料表LOB(Image/Text)資料到其他File Group

當資料表中有nvarchar(max)這種大型欄位時,該資料表資料存放就會有兩個部分,一個是Row Data一個是LOB,當單一筆資料進來時該大型欄位資料內容過大無法在單一Page存放時,就會被SQL放到LOB區域去。

而LOB在建立資料表時不指定存放區則預設會放到Primary這一個File Group中。但如果我們事後想調整更換時該怎麼做呢?

首先用下面語法建立一資料表後,預設狀況下該資料表的Row Data及LOB物件存放區都會是在Primary中

Create Table BigTable(
	Id int Identity Primary Key Clustered,
	msg nvarchar(max)
)On [Primary];
GO


SELECT
    OBJECT_NAME(p.object_id) AS table_name,
    p.index_id,
    p.rows,
    au.type_desc AS alloc_unit_type,
    au.used_pages,
    fg.name AS fg_name
FROM sys.partitions as p
JOIN sys.allocation_units AS au on p.hobt_id = au.container_id
JOIN sys.filegroups AS fg on fg.data_space_id = au.data_space_id
WHERE p.object_id = OBJECT_ID('BigTable')
ORDER BY table_name, index_id, alloc_unit_type;
GO

上述執行完如下圖所示

預設File Group會是Primary

也可以用在建立Table時指定該Table的Row Data及LOB物件存放區,如下語法

Create Table BigTable2(
	Id int Identity Primary Key Clustered,
	msg nvarchar(max)
)On [SecGroup] TEXTIMAGE_ON [SecGroup] ;
GO


SELECT
    OBJECT_NAME(p.object_id) AS table_name,
    p.index_id,
    p.rows,
    au.type_desc AS alloc_unit_type,
    au.used_pages,
    fg.name AS fg_name
FROM sys.partitions as p
JOIN sys.allocation_units AS au on p.hobt_id = au.container_id
JOIN sys.filegroups AS fg on fg.data_space_id = au.data_space_id
WHERE p.object_id = OBJECT_ID('BigTable2')
ORDER BY table_name, index_id, alloc_unit_type;
GO

上述執行完如下圖所示

建立資料表時將File Group設為SecGroup

但一旦資料表建立完成後想要移動資料表至別的File Group時可以使用下面語法,但執行後會發現SQL只會將Row Data轉移至新指定的File Group,而LOB物件依然在舊的File Group。

CREATE UNIQUE CLUSTERED INDEX PK__BigTable
ON dbo.BigTable ( [ID] )
WITH (ONLINE = ON, DROP_EXISTING = ON)
ON [SecGroup];
指定File Group來重建索引,只會搬移Row Data資料,LOB不變

面對上述問題可改用 PartitionFunction達到轉移LOB物件的目的,如下語法

--建立PARTITION FUNCTION,預計分割資料的值就填入一個比BigTable的ID更大值
--下面我先填入10000
CREATE PARTITION FUNCTION pf_MyTable(INT)
AS RANGE RIGHT FOR VALUES (10000);

--建立PARTITION SCHEME,小於10000會放到[SecGroup],大於就放到[PRIMARY]
CREATE PARTITION SCHEME ps_MyTable
AS PARTITION pf_MyTable
TO ( [SecGroup], [PRIMARY] );

--套用PARTITION SCHEME來Rebuild BigTable的Clustered Index。
CREATE UNIQUE CLUSTERED INDEX [PK__BigTable]
ON [dbo].[BigTable]([ID])
WITH (ONLINE = ON, DROP_EXISTING = ON)
ON ps_MyTable ([ID]);


--完成上述步驟後BigTable的Row Data跟LOB應該都轉入[SecGroup]
--此時我們再重建一次BigTable的Clustered Index,這次不套用PARTITION SCHEME
CREATE UNIQUE CLUSTERED INDEX [PK__BigTable]
ON [dbo].[BigTable]([ID])
WITH (DROP_EXISTING = ON, ONLINE = ON)
ON [SecGroup];

--完成轉移後,刪除PARTITION SCHEME
DROP PARTITION SCHEME ps_MyTable;
DROP PARTITION FUNCTION pf_MyTable;

完成上述語法後就會如下圖所示,BigTable的Row Data跟LOB都轉入[SecGroup]

轉換File Group完成

 

我是ROCK

rockchang@mails.fju.edu.tw