以 SQL Variant 作为列之一的非聚集索引如何工作?
How does a non-clustered index with SQL Variant as one of the columns work?
我有一个 table 包含以下列
Id - Int Primary key Identity column
Name - Varchar(100)
OrderValue - int
OrderDate - date
OrderState - varchar(100)
列 (Name, orderValue) 具有唯一键约束和唯一非聚集索引。
我们有一个新要求,OrderValue 列将开始接收字符串、浮点数和 GUID。我们现在有两个选择,将 orderValue 的数据类型更改为 Varchar(100) 或 SQL_Variant。我的队友都赞成sql_variant。他们的理由是,由于 orderValue 是唯一非聚集索引的一部分,因此更改它 sql_variant 将使索引 table 中的索引键的排序变得容易,因为相同类型的所有数据类型都存储在一起.我不太熟悉 Sql_variant 以及如何为 sql_variant 存储索引,但我读到 sql_variant 的性能通常很差。在我们的例子中,什么是好的选择?当非聚集索引的其中一列为 sql_variant?
时,它们如何工作
我自己从未使用过这种数据类型。
更新:
找到一篇演示如何使用 SQL_VARIANT
数据类型的文章:https://aboutsqlserver.com/2012/02/22/store-custom-fieldsattributes-in-microsoft-sql-server-database-part-2-namevalue-pairs/?unapproved=201416&moderation-hash=771c41a02ff9a7c909e93140a8795e3a#comment-201416
订购
从阅读 documentation, specifically value comparison part 我可以看出在某些情况下排序看起来不“自然”,例如
CREATE TABLE #Test( a SQL_VARIANT )
INSERT INTO #Test VALUES( 2 ) -- INT
INSERT INTO #Test VALUES( 2.1 ) -- DECIMAL
INSERT INTO #Test VALUES( '3' ) -- VARCHAR
INSERT INTO #Test VALUES( CAST( 1.8 AS FLOAT ) )
INSERT INTO #Test VALUES( DATEFROMPARTS( 2020, 1, 1 ) )
SELECT *, SQL_VARIANT_PROPERTY ( a , 'BaseType' ) FROM #Test ORDER BY a
DROP TABLE #Test
结果(按列 a
升序排列):
a
-------------------------- -----------
3 varchar
2 int
2.1 numeric
1.8 float
2020-01-01 00:00:00.000 date
指数表现
我认为索引查找不会有任何性能问题。插入和更新可能会受到惩罚
陷阱
使用这种数据类型时会遇到很多小问题。下面是一些示例:
1| WHERE
条件将不匹配,除非数据类型匹配:
-- Returns nothing
SELECT *, SQL_VARIANT_PROPERTY ( a , 'BaseType' ), SQL_VARIANT_PROPERTY ( a , 'TotalBytes' )
FROM #Test
WHERE a = '2'
ORDER BY a
-- Returns nothing
SELECT *, SQL_VARIANT_PROPERTY ( a , 'BaseType' ), SQL_VARIANT_PROPERTY ( a , 'TotalBytes' )
FROM VariantTest
WHERE a = 3
ORDER BY a
2|这不会插入具有正确数据类型的数据,因为数据类型将首先隐式转换为 VARCHAR
,然后再转换为 SQL_VARIANT
:
INSERT INTO #Test VALUES( 2 ), ( 2.1 ), ( '3' ), CAST( 1.8 AS FLOAT )
我有一个 table 包含以下列
Id - Int Primary key Identity column
Name - Varchar(100)
OrderValue - int
OrderDate - date
OrderState - varchar(100)
列 (Name, orderValue) 具有唯一键约束和唯一非聚集索引。
我们有一个新要求,OrderValue 列将开始接收字符串、浮点数和 GUID。我们现在有两个选择,将 orderValue 的数据类型更改为 Varchar(100) 或 SQL_Variant。我的队友都赞成sql_variant。他们的理由是,由于 orderValue 是唯一非聚集索引的一部分,因此更改它 sql_variant 将使索引 table 中的索引键的排序变得容易,因为相同类型的所有数据类型都存储在一起.我不太熟悉 Sql_variant 以及如何为 sql_variant 存储索引,但我读到 sql_variant 的性能通常很差。在我们的例子中,什么是好的选择?当非聚集索引的其中一列为 sql_variant?
时,它们如何工作我自己从未使用过这种数据类型。
更新:
找到一篇演示如何使用 SQL_VARIANT
数据类型的文章:https://aboutsqlserver.com/2012/02/22/store-custom-fieldsattributes-in-microsoft-sql-server-database-part-2-namevalue-pairs/?unapproved=201416&moderation-hash=771c41a02ff9a7c909e93140a8795e3a#comment-201416
订购
从阅读 documentation, specifically value comparison part 我可以看出在某些情况下排序看起来不“自然”,例如
CREATE TABLE #Test( a SQL_VARIANT )
INSERT INTO #Test VALUES( 2 ) -- INT
INSERT INTO #Test VALUES( 2.1 ) -- DECIMAL
INSERT INTO #Test VALUES( '3' ) -- VARCHAR
INSERT INTO #Test VALUES( CAST( 1.8 AS FLOAT ) )
INSERT INTO #Test VALUES( DATEFROMPARTS( 2020, 1, 1 ) )
SELECT *, SQL_VARIANT_PROPERTY ( a , 'BaseType' ) FROM #Test ORDER BY a
DROP TABLE #Test
结果(按列 a
升序排列):
a
-------------------------- -----------
3 varchar
2 int
2.1 numeric
1.8 float
2020-01-01 00:00:00.000 date
指数表现
我认为索引查找不会有任何性能问题。插入和更新可能会受到惩罚
陷阱
使用这种数据类型时会遇到很多小问题。下面是一些示例:
1| WHERE
条件将不匹配,除非数据类型匹配:
-- Returns nothing
SELECT *, SQL_VARIANT_PROPERTY ( a , 'BaseType' ), SQL_VARIANT_PROPERTY ( a , 'TotalBytes' )
FROM #Test
WHERE a = '2'
ORDER BY a
-- Returns nothing
SELECT *, SQL_VARIANT_PROPERTY ( a , 'BaseType' ), SQL_VARIANT_PROPERTY ( a , 'TotalBytes' )
FROM VariantTest
WHERE a = 3
ORDER BY a
2|这不会插入具有正确数据类型的数据,因为数据类型将首先隐式转换为 VARCHAR
,然后再转换为 SQL_VARIANT
:
INSERT INTO #Test VALUES( 2 ), ( 2.1 ), ( '3' ), CAST( 1.8 AS FLOAT )