將十進位資料儲存成可變長度
decimal 和 numeric 資料類型通常會在磁碟上儲存成固定長度資料。numeric 資料類型在功能上等同於 decimal 資料類型。在 SQL Server 2005 Service Pack 2 (SP2) 和更新版本中,decimal 和 numeric 資料類型可使用 Vardecimal 儲存格式來儲存成可變長度資料行。Vardecimal 儲存格式僅適用於 SQL Server Enterprise、Developer 和 Evaluation Edition。
[!附註]
未來的 Microsoft SQL Server 版本將移除這項功能。請避免在新的開發工作中使用這項功能,並規劃修改目前使用這項功能的應用程式。 請改用 ROW 和 PAGE 壓縮。如需詳細資訊,請參閱<建立壓縮資料表及索引>。
[!附註]
Vardecimal 是一種儲存格式,而非資料類型。
Vardecimal 儲存格式可能會大幅縮減資料的儲存大小,但是卻會增加少量的 CPU 負擔。Vardecimal 儲存格式是在資料表層級套用的。這表示您可以使用 Vardecimal 儲存格式來儲存資料表的某些 decimal 資料行,而無法儲存其他資料行。decimal 資料會維持確切的資料類型。
在資料表上啟用 Vardecimal 儲存格式時,decimal 資料就會以 Vardecimal 儲存格式儲存於資料、索引和記錄頁面中。變更儲存格式是一項離線作業。修改的資料表在進行此作業期間會以獨佔方式鎖定,而且無法用於並行讀取或寫入存取。
Vardecimal 儲存格式的實作
根據資料行的有效位數而定 (1 至 38),decimal 值的儲存會耗用 5 至 17 個位元組。如果資料表沒有使用 Vardecimal 儲存格式,則資料表中的每個項目都會針對每個已定義的十進位資料行耗用相同的位元組數目,即使資料列的值為 0、NULL 或可用較少位元組數目表示的某些值 (例如數字 3) 也一樣。當資料表以 Vardecimal 儲存格式儲存時,每個資料列的 decimal 資料行就只會耗用容納已提供之數字所需的空間,加上 2 個位元組的負擔。其結果一定會介於 5 至 20 個位元組之間。這包括儲存值位移的 2 個位元組的負擔。不過,Null 值和零會以特殊方式處理並且僅採取 2 個位元組。
如果資料表沒有任何可變長度資料行,每個資料列就會有 2 個位元組的額外負擔,可儲存可變長度資料行的數目。如果資料表至少已經有一個可變長度資料行,就不會有任何額外負擔。
下表將顯示用一般固定格式儲存十進位資料所需的位元組數目,以及用 Vardecimal 儲存格式儲存十進位資料所需的最大位元組數目。當資料表是以固定格式儲存時,所列出的值將用於每個資料列。當資料表是以 Vardecimal 儲存格式儲存時,許多值所需的位元組數目將會比列出的位元組數目要少。
資料行有效位數 |
原始固定十進位大小 (位元組) |
最大 Vardecimal 資料區域 (位元組) |
儲存位移的負擔 (位元組) |
使用的最大 Vardecimal 儲存體 (位元組) |
---|---|---|---|---|
1-3 |
5 |
3 |
2 |
5 |
4-6 |
5 |
4 |
2 |
6 |
7-9 |
5 |
5 |
2 |
7 |
10-12 |
9 |
6 |
2 |
8 |
13-15 |
9 |
8 |
2 |
10 |
16-18 |
9 |
9 |
2 |
11 |
19 |
9 |
10 |
2 |
12 |
20-21 |
13 |
10 |
2 |
12 |
22-24 |
13 |
11 |
2 |
13 |
25-27 |
13 |
13 |
2 |
15 |
28 |
13 |
14 |
2 |
16 |
29-30 |
17 |
14 |
2 |
16 |
31-33 |
17 |
15 |
2 |
17 |
34-36 |
17 |
16 |
2 |
18 |
37-38 |
17 |
18 |
2 |
20 |
使用 Vardecimal 儲存格式
當您嘗試解決下列問題時,可以使用 Vardecimal 儲存格式:
磁碟空間不足。
磁碟存取 (I/O) 是系統效能的瓶頸。
您必須針對某些資料擁有高階有效位數,即使其中許多值很小、為 NULL 或 0 也一樣 (例如,資料倉儲中的資料表含有 decimal 資料行,而且該資料行具有許多包含 0 或整數值的資料列)。
變更資料表的儲存格式需要重建資料表的儲存體 (叢集索引或堆積)。如果資料表的叢集索引包含 decimal 資料行,您也必須重建所有非叢集索引,因為它們包含叢集索引鍵值。如果叢集索引沒有 decimal 資料行,而非叢集索引包含 decimal 資料行,就會重建非叢集索引。如果資料表為堆積 (亦即,沒有叢集索引),您就必須重建所有非叢集索引,以便指向堆積中的新資料列位置。
重建資料表來啟用或停用 Vardecimal 儲存格式可能需要原始資料表兩倍以上的總儲存空間。如果資料表沒有包含 decimal 或 numeric 資料行,則啟用 Vardecimal 儲存格式就只是中繼資料作業。重建資料表和索引時,預期會有大量記錄活動。
Vardecimal 儲存格式可用於唯讀和可讀寫資料表。儲存空間的節省程度必須與針對每次存取資料列時轉換資料列儲存格式所需的額外 CPU 使用量取得平衡。此外,寫入使用 Vardecimal 儲存格式的資料表可能會降低效能,因為頁面分割的數目會增加。
Vardecimal 儲存格式的限制
系統會套用下列限制:
需要 SQL Server 2005 SP2 或更新版本。
Vardecimal 儲存格式無法在系統資料庫中啟用:master、model、msdb、tempdb 或 distribution。當查詢排序用 Vardecimal 儲存格式儲存的資料時,這項資料就會以固定十進位狀態儲存於 tempdb 中。一般而言,這項資料在 tempdb 中所需的空間會明顯比來源資料庫中 Vardecimal 儲存格式來源資料表所佔用的空間更多。
Vardecimal 儲存格式無法套用至檢視、索引檢視、XML 索引和全文檢索索引。不過,這些物件的基礎資料表可以使用 Vardecimal 儲存格式。
內部資料表 (例如中繼資料和通知資料表) 無法使用 Vardecimal 儲存格式。
資料表值函數無法使用 Vardecimal 儲存格式。
儲存於 Vardecimal 儲存格式資料表中的 numeric 資料行也無法加密。
不支援異質資料分割 (亦即,固定十進位格式和 Vardecimal 儲存格式資料分割)。
使用 Transact-SQL SELECT … INTO… 語法並根據 Vardecimal 儲存格式資料表建立的新資料表不會繼承 Vardecimal 儲存格式。
啟用資料庫鏡像的資料庫無法變更其 Vardecimal 儲存格式狀態。您必須移除資料庫鏡像,才能在資料庫上啟用 Vardecimal 儲存格式。不過,如果有個別資料表啟用或停用 Vardecimal 儲存格式,您就不需要移除資料庫鏡像。
SQL Server 必須能夠保證所有更新都會成功,而且資料表一定可以返回固定十進位格式。因此,如果有額外負擔導致現有資料列超過 8060 個位元組,或者現有的索引值超過 900 個位元組,資料表就無法變更為 Vardecimal 儲存格式。
[!附註]
Vardecimal 儲存格式與變數文字 (varchar) 儲存的不同之處在於,如果所有變數資料行都處於大小上限的狀態,SQL Server 可讓您建立超過 8060 個位元組的資料列。插入或更新文字資料時,SQL Server 會強制執行 8060 個位元組的限制。SQL Server 無法讓您建立單一資料列超過 8060 個位元組限制的十進位資料行集合。當資料表格式變更為 Vardecimal 儲存時,就會強制執行 8060 個位元組的限制。
當您使用「複製資料庫精靈」的卸離和附加方法來傳送資料庫時,如果目的地 Database Engine 不是 SQL Server 2005 SP2 或更新版本,附加作業就會失敗。SQL Server 管理物件 (SMO) 方法將會建立新的資料庫和資料表,但不使用 Vardecimal 儲存格式。如果 Database Engine 是 SQL Server 2005 SP2 或更新版本,則在傳送之後,資料庫和資料表就可以變更為 Vardecimal 格式。
備份和復原、資料庫鏡像、sp_attach_db 和記錄傳送
備份和復原、資料庫鏡像、sp_attach_db 和記錄傳送可搭配 Vardecimal 儲存格式正常運作。不過,若要加入使用 Vardecimal 儲存格式的資料庫,每個 SQL Server 執行個體至少都必須升級為 SQL Server 2005 SP2。例如,您無法將啟用 Vardecimal 儲存格式之資料庫的記錄備份還原至未啟用的資料庫、無法從啟用 Vardecimal 儲存格式的資料庫鏡像至未啟用的資料庫,也無法將啟用 Vardecimal 儲存格式的資料庫從 SQL Server 2005 SP2 附加至舊版 SQL Server。如果您要將啟用 Vardecimal 儲存格式之資料庫的完整備份還原至未啟用 Vardecimal 儲存格式的資料庫,資料庫將會成為啟用 Vardecimal 儲存格式。
當資料表變更為 Vardecimal 儲存格式時,記錄備份鏈結會維持有效,而且您可以套用上次完整備份加上有效的記錄鏈結來還原資料庫。若要避免建立無效的備份,您必須將資料庫變更為簡單復原模式,然後再修改任何資料表,以便移除 Vardecimal 儲存格式。在您移除任何資料表的 Vardecimal 儲存格式之後,就應該建立完整資料庫備份。
使用 Vardecimal 儲存格式搭配資料庫鏡像
下列程序會提供使用 Vardecimal 儲存格式搭配資料庫鏡像的步驟。
使用 Vardecimal 儲存格式搭配資料庫鏡像
讓主體和鏡像夥伴執行個體至少成為 SQL Server 2005 SP2。
如果您目前正在使用資料庫鏡像,請移除資料庫鏡像並刪除鏡像夥伴。如需詳細資訊,請參閱<如何:移除資料庫鏡像 (Transact-SQL)>。
在主體資料庫 (如果資料庫位於 SQL Server 2005) 上啟用 Vardecimal 儲存格式,並確定主體資料庫處於完整復原模式。
使用主體資料庫的完整和記錄備份,藉以建立資料庫鏡像。如需詳細資訊,請參閱<如何:使用 Windows 驗證建立資料庫鏡像工作階段 (Transact-SQL)>。
將個別資料表修改成使用 Vardecimal 儲存格式。
[!附註]
您不需要移除資料庫鏡像來變更個別資料表的儲存格式。
移除 Vardecimal 儲存格式
修改主體資料庫中的資料表,以便移除 Vardecimal 儲存格式。
移除資料庫鏡像。
將主體資料庫設定為簡單復原模式。這就會中斷記錄鏈結。
如果資料庫位於 SQL Server 2005,請在主體資料庫上停用 Vardecimal 儲存格式。
卸除鏡像夥伴資料庫。
將主體資料庫變更回完整復原模式。
備份主體資料庫並重新建立資料庫鏡像。
Vardecimal 儲存格式對複寫作業造成的影響
複寫可正常地在使用 Vardecimal 儲存格式的資料表上運作,但是具有下列考量事項:
在複寫期間,用 Vardecimal 儲存格式儲存的 decimal 資料類型會轉換成固定十進位格式,以便進行傳送。distribution 資料庫無法啟用 Vardecimal 儲存格式。因此,當資料儲存於 distribution 資料庫的複寫資料表時,它不會用 Vardecimal 儲存格式儲存。在訂閱者端,記錄會按一般方式套用。
Vardecimal 儲存格式資料表可複寫至固定十進位格式資料表,而固定十進位格式資料表也可複寫至 Vardecimal 儲存格式資料表。
與新訂閱相關的建立資料表處理序不會使用 Vardecimal 儲存格式來建立資料表。不論 Database Engine 的 Service Pack 層級,或訂閱資料庫的 Vardecimal 儲存格式啟用狀態為何,這都會讓複寫成功。在建立資料表之後或在套用建立指令碼之前透過修改指令碼,訂閱資料表即可在訂閱者端啟用 Vardecimal 儲存格式。
下表將描述各種訂閱者的指令碼需求。
訂閱者 |
指令碼 |
---|---|
SQL Server 2000 或 SQL Server 7.0 版。 |
建立資料表指令碼可直接使用而不用修改。 |
SQL Server 2005 資料庫未標示為 Vardecimal 儲存格式。 |
建立資料表指令碼可直接使用而不用修改。 |
SQL Server 2005 資料庫標示為 Vardecimal 儲存格式,但是您不想讓訂閱者資料表啟用 Vardecimal 儲存格式。 |
建立資料表指令碼可直接使用而不用修改。 |
SQL Server 2005 資料庫標示為 Vardecimal 儲存格式,而且您想讓 SQL Server 2005 訂閱者資料表啟用 Vardecimal 儲存格式。 |
您可以將建立資料表指令碼修改成在資料庫中啟用 Vardecimal 儲存格式並啟用資料表的 Vardecimal 儲存格式。或者,您也可以透過使用後面<啟用 Vardecimal 儲存格式>一節所述的預存程序,啟用訂閱者資料庫和資料表。 |
其他考量
下面是當您在處理 Vardecimal 儲存格式時應該注意的其他考量事項清單:
Vardecimal 儲存格式對於大量匯入和匯出 (bcp) 作業沒有任何影響。
DATALENGTH 函數不會偵測 Vardecimal 儲存格式,而會傳回可用固定十進位格式儲存的位元組數目。
在極少數的情況下,Vardecimal 儲存格式會讓 SQL Server 無法使用針對固定十進位格式最佳化的查詢計畫。
Vardecimal 儲存格式可搭配任何資料庫相容性層級使用。
在執行 sp_tableoption 時,如果資料表沒有 decimal 或 numeric 資料類型的資料行,資料表中繼資料就會變更,以指示資料表使用 Vardecimal 儲存格式。日後加入新的 decimal 資料行時,這些資料行將會用 Vardecimal 儲存格式儲存。在使用 Vardecimal 儲存格式的資料表中加入或移除資料行時,不需要運用任何特殊技術。
啟用 Vardecimal 儲存格式
啟用或變更 Vardecimal 儲存格式需要下列權限:
在資料庫中啟用 Vardecimal 儲存格式需要伺服器的 ALTER DATABASE 權限。
將資料表變更為 Vardecimal 儲存格式需要資料表的 ALTER 權限。
在您啟用 Vardecimal 儲存格式之前,應該先確認資料表在啟用 Vardecimal 儲存格式之後將會壓縮。如果大部分資料列都需要已定義的資料行有效位數,則與 Vardecimal 儲存格式相關聯的負擔可能會比空間節省程度更大,因而產生較大的資料表。若要在修改資料表之前預估資料列大小縮減,請使用 sp_estimated_rowsize_reduction_for_vardecimal 預存程序。如果您決定要變更資料表的儲存格式,請啟用資料庫的 Vardecimal 儲存格式,然後啟用個別資料表的 Vardecimal 儲存格式。SQL Server 2008 資料庫不需啟用 Vardecimal 儲存格式。
在 SQL Server 2008 資料庫中,您可以透過使用預存程序或 SQL Server Management Studio,啟用 decimal 資料類型的 Vardecimal 儲存格式:
請執行 sp_db_vardecimal_storage_format 來啟用資料庫的 Vardecimal 儲存格式 (如果 SQL Server 的執行個體是 SQL Server 2005 SP 2),然後執行 sp_tableoption 來啟用適當資料表的 Vardecimal 儲存格式。
在 Management Studio 中,使用 [資料庫屬性選項頁面] 來啟用資料庫的 Vardecimal 儲存格式。您必須使用 sp_tableoption,將資料表變更為 Vardecimal 儲存格式。
[!附註]
從 SQL Server 2008 開始,所有資料庫都會啟用 Vardecimal 儲存格式。
識別 Vardecimal 儲存格式資料表
若要判斷資料庫中的哪些資料表正在使用 Vardecimal 儲存格式,請使用 OBJECTPROPERTY 函數並搜尋 TableHasVarDecimalStorageFormat 屬性。
如果 Production.WorkOrderRouting 資料表使用 Vardecimal 儲存格式,下列範例就會傳回 1,但是如果沒有使用此格式,就會傳回 0。
USE AdventureWorks ;
GO
SELECT OBJECTPROPERTY(OBJECT_ID('Production.WorkOrderRouting'),
'TableHasVarDecimalStorageFormat') ;
GO
下列範例會在 AdventureWorks 資料庫中搜尋使用 Vardecimal 儲存格式的所有資料表。
USE AdventureWorks ;
GO
SELECT name, object_id, type_desc
FROM sys.objects
WHERE OBJECTPROPERTY(object_id,
N'TableHasVarDecimalStorageFormat') = 1 ;
GO
移除 Vardecimal 儲存格式時發生的問題
若要從資料表中移除 Vardecimal 儲存格式,您必須用固定十進位格式來重建資料表。這可能會大幅增加資料表所使用的磁碟空間。如果沒有足夠的磁碟空間,這項作業將會失敗。在此情況下,若要停用 Vardecimal 儲存格式,您必須確定 SQL Server 有足夠的磁碟空間可用。此外,擴充作業也需要暫存空間來儲存 Vardecimal 和一般格式的資料。如果擴充的資料表在擴充之後可容納在可用磁碟空間中,但僅由於暫存磁碟空間不足而無法擴充,您就可以透過將資料表的資料列複製到新的未擴充資料表,以累加方式擴充資料。
若要在修改資料庫之後立即從資料庫中移除 Vardecimal 儲存格式,請卸除資料庫,然後從啟用資料庫 Vardecimal 儲存格式之前建立的備份還原資料庫。
當您要將資料庫從 SQL Server 2005 Enterprise、Developer 或 Evaluation Edition 移至另一個版本或舊版 SQL Server 時,必須先使用其中一個所需的版本來開啟資料庫、移除 Vardecimal 儲存格式,然後再移轉資料庫。如果您將包含 Vardecimal 儲存格式的資料庫附加至不適用的伺服器,附加作業就會失敗。