-- Find columns in user tables that cannot be included in a columnstore index.
-- These restrictions apply to both clustered and non-clustered columnstore indexes.
-- SQL Server 2014: http://msdn.microsoft.com/en-us/library/gg492153(v=sql.120).aspx
-- SQL Server 2012: http://msdn.microsoft.com/en-us/library/gg492153(v=sql.110).aspx
-- Get the version number of SQL Server
DECLARE @ServerVersion TINYINT = CONVERT(INT,SUBSTRING(CONVERT(VARCHAR,SERVERPROPERTY('ProductVersion')),1,(CHARINDEX('.',(CONVERT(VARCHAR,SERVERPROPERTY('ProductVersion'))))-1)))
IF @ServerVersion = 11
-- This section is only for SQL Server 2012
BEGIN
SELECT
s.name AS 'SchemaName'
,o.name AS 'TableName'
,c.name AS 'ColumnName'
,'ColumnType' = CASE t.name
WHEN 'decimal' THEN t.name + '(' + CONVERT(VARCHAR,c.precision) + ',' + CONVERT(VARCHAR,c.scale) + ')'
WHEN 'numeric' THEN t.name + '(' + CONVERT(VARCHAR,c.precision) + ',' + CONVERT(VARCHAR,c.scale) + ')'
WHEN 'varchar' THEN
CASE c.max_length
WHEN -1 THEN 'varchar(max)'
ELSE 'varchar(' + CONVERT(VARCHAR,c.max_length) + ')'
END
WHEN 'nvarchar' THEN
CASE c.max_length
WHEN -1 THEN 'nvarchar(max)'
ELSE 'nvarchar(' + CONVERT(VARCHAR,c.max_length) + ')'
END
WHEN 'datetimeoffset' THEN t.name + '(' + CONVERT(VARCHAR,c.scale) + ')'
ELSE t.name
END
,'ColumnAttribute' = CASE
WHEN (c.is_filestream = 1) THEN 'Filestream'
WHEN (c.is_sparse = 1) THEN 'Sparse'
ELSE ''
END
FROM sys.columns c
JOIN sys.objects o ON c.object_id = o.object_id
JOIN sys.types t ON c.user_type_id = t.user_type_id
JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE o.is_ms_shipped <> 1
-- These types cannot be part of a SQL Server 2012 columnstore index
AND (
t.name IN
('binary'
,'varbinary'
,'ntext'
,'text'
,'image'
,'uniqueidentifier'
,'rowversion'
,'timestamp'
,'sql_variant'
,'hierarchyid'
,'geography'
,'geometry'
,'xml')
OR (
-- Decimal & numeric cannot have a precision over 18
t.name IN ('decimal','numeric')
AND c.precision > 18)
OR (
-- Varchar(max) and nvarchar(max)
t.name = 'datetimeoffset'
AND c.scale > 2)
OR (
-- Varchar(max) and nvarchar(max)
t.name IN ('varchar','nvarchar')
AND c.max_length = -1)
OR (
-- Filestream
c.is_filestream = 1)
OR (
-- Sparse
c.is_sparse = 1)
)
ORDER BY s.name,o.name,c.column_id
END
ELSE IF @ServerVersion = 12
-- This section is only for SQL Server 2014
BEGIN
SELECT
s.name AS 'SchemaName'
,o.name AS 'TableName'
,c.name AS 'ColumnName'
,'ColumnType' = CASE t.name
WHEN 'varchar' THEN
CASE c.max_length
WHEN -1 THEN 'varchar(max)'
ELSE 'varchar(' + CONVERT(VARCHAR,c.max_length) + ')'
END
WHEN 'nvarchar' THEN
CASE c.max_length
WHEN -1 THEN 'nvarchar(max)'
ELSE 'nvarchar(' + CONVERT(VARCHAR,c.max_length) + ')'
END
ELSE t.name
END
,'ColumnAttribute' = CASE
WHEN (c.is_filestream = 1) THEN 'Filestream'
WHEN (c.is_sparse = 1) THEN 'Sparse'
ELSE ''
END
FROM sys.columns c
JOIN sys.objects o ON c.object_id = o.object_id
JOIN sys.types t ON c.user_type_id = t.user_type_id
JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE o.is_ms_shipped <> 1
-- These types cannot be part of a SQL Server 2014 columnstore index
AND (
t.name IN
('ntext'
,'text'
,'image'
,'rowversion'
,'timestamp'
,'sql_variant'
,'hierarchyid'
,'geography'
,'geometry'
,'xml')
OR (
-- Varchar(max) and nvarchar(max)
t.name IN ('varchar','nvarchar')
AND c.max_length = -1)
OR (
-- Filestream
c.is_filestream = 1)
OR (
-- Sparse
c.is_sparse = 1)
)
ORDER BY s.name,o.name,c.column_id
END
ELSE
BEGIN
RAISERROR ('This script only works on SQL Server 2012 and SQL Server 2014.',16,1);
END
GO
Running this against your database will output an organized list of tables along with the column name and data type that cannot be used within a Columnstore index.
The script can be used if you plan to create a clustered or non-clustered index, since the data type restrictions would apply to both. The script can also be used to analyze databases in either SQL Server 2012 or 2014.
You can read more about the limitations and restrictions of Columnstore indexes in Books Online.

No comments:
Post a Comment