由於在SQL Server 2008中引入了新的稀疏列功能,現在就有可能把列聲明為稀疏列並且任何時候在列中輸入一個空值它都不會消耗任何空間。其中一個技巧是找出何時確定是否把一個列定義稀疏列。
在下面的例子中,Address Lines 1 到 3是要求的,Address Lines 4和5是不要求的但是經常使用的,Address Lines 6到8很少使用。當創建Address Lines 6到8時,我們使用稀疏選項,這是因為我們知道這個數據很少存儲下來。
CREATE TABLE CustomerInfo
(CustomerID INT PRIMARY KEY,
Address_Line1 VARCHAR(100) NOT NULL,
Address_Line2 VARCHAR(100) NOT NULL,
Address_Line3 VARCHAR(100) NOT NULL,
Address_Line4 VARCHAR(100) NULL,
Address_Line5 VARCHAR(100) NULL,
Address_Line6 VARCHAR(100) SPARSE NULL,
Address_Line7 VARCHAR(100) SPARSE NULL,
Address_Line8 VARCHAR(100) SPARSE NULL,
)
那麼為什麼不干脆把所有的列都聲明為稀疏列呢?
稀疏列需要額外的4個字節來在表中存儲非空值固定長度數據類型值並且要求零字節來存儲一個空值;因此,在每一個數據類型上擁有正確的阈值是很重要的,或者你可以使用更多的空間而不是獲得它來結束。一個數據類型使用的字節越少,用來節約空間的空值百分比要求就越高。
在MSDN的一張表中有使用稀疏列的建議百分比。看看這個可以幫助你確定何時可以獲得使用稀疏列的益處。
使用這張表作為准則,下面的腳本將會確認任何可能獲得新的稀疏列功能的列。通過搜索數據庫中超過一定阈值的空值的列,你可以很容易地分析結果並且確定這個新功能是否可用。固定長度列的阈值存儲在一個臨時表中。依賴於精確度和長度的數據類型將默認為60%。
USE AdventureWorks
GO
SET NOCOUNT ON
DECLARE @SQL VARCHAR(MAX)
CREATE TABLE #SPARCEPERCENTAGE (
DATATYPE VARCHAR(50),
PRCENT INT)
INSERT INTO #SPARCEPERCENTAGE
SELECT 'bit', 98
UNION ALL
SELECT 'tinyint', 86
UNION ALL
SELECT 'smallint', 76
UNION ALL
SELECT 'int', 64
UNION ALL
SELECT 'bigint', 52
UNION ALL
SELECT 'real', 64
UNION ALL
SELECT 'float', 52
UNION ALL
SELECT 'smallmoney', 64
UNION ALL
SELECT 'money', 52
UNION ALL
SELECT 'smalldatetime', 64
UNION ALL
SELECT 'datetime', 52
UNION ALL
SELECT 'uniqueidentifier', 43
UNION ALL
SELECT 'date', 69
CREATE TABLE #TMP (
CLMN VARCHAR(500),
NULLCOUNT INT,
DATATYPE VARCHAR(50),
TABLECOUNT INT)
SELECT @SQL = COALESCE(@SQL,'') + CAST('INSERT INTO #TMP Select ''' + TABLE_SCHEMA + '.' + REPLACE(TABLE_NAME,'''','''''') + '.' + COLUMN_NAME + ''' AS Clmn, count(*) NullCount, ''' + DATA_TYPE + ''', (Select count(*) FROM ' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']) AS TableCount FROM ' + TABLE_SCHEMA + '.[' + TABLE_NAME + '] WHERE [' + COLUMN_NAME + '] IS NULL ;' + CHAR(13) AS VARCHAR(MAX))
FROM INFORMATION_SCHEMA.COLUMNS
JOIN sysobjects B
ON INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = B.NAME
WHERE XTYPE = 'U'
--AND INFORMATION_SCHEMA.COLUMNS.TABLE_SCHEMA = 'Person'
--AND INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = 'Contact'
EXEC( @SQL)
SELECT A.CLMN,
A.NULLCOUNT,
A.TABLECOUNT,
A.DATATYPE,
(A.NULLCOUNT * 1.0 / A.TABLECOUNT) NULLPERCENT,
ISNULL(B.PRCENT,60) * .01 VALUEPERCENT
FROM #TMP A
LEFT JOIN #SPARCEPERCENTAGE B
ON A.DATATYPE = B.DATATYPE
WHERE A.NULLCOUNT > 0
AND (A.NULLCOUNT * 1.0 / A.TABLECOUNT) >= ISNULL(B.PRCENT,60) * .01
ORDER BY NULLPERCENT DESC
DROP TABLE #TMP
DROP TABLE #SPARCEPERCENTAGE