我正在创建一个可能包含数百万条记录的 SQL Server 2008 数据库,我想知道是否需要将以下内容定义为索引:
可能只包含 0 和 1 的 TINYINT 列?
TINYINT 列可能仅包含:0、5 和 6?
PS。这两个列都将在 WHERE 子句中用于选择。
我正在创建一个可能包含数百万条记录的 SQL Server 2008 数据库,我想知道是否需要将以下内容定义为索引:
可能只包含 0 和 1 的 TINYINT 列?
TINYINT 列可能仅包含:0、5 和 6?
PS。这两个列都将在 WHERE 子句中用于选择。
不,基本上不会单独使用这些列上的索引。
但是这种低选择性键非常适合组合键,作为索引中最左边的列。例如,说TINYINT (0,1)
(为什么不使用bit
btw?)是deleted
列。您经常查询以 . 为谓词WHERE deleted=0 AND ...
。将此添加为聚集索引中最左边的列通常是正确的方法。或者,如果谓词是,比如说,WHERE name = '...' AND deleted=0
你应该做一个非聚集的index on (deleted, name)
。
另一种选择是使用过滤索引:create index .. on (name) where (deleted=0)
但这并不涵盖您对deleted=1
.
对于具有很少不同值的列(例如type
列)也是如此。同样,使其成为复合索引中最左边的键通常很有意义。
请注意,如果您在索引中添加一个低选择性键作为最左边的键,并且您没有在谓词中指定此列(例如,不WHERE name='...'
添加任何条件deleted
),则无法使用索引,只能使用索引on (name)
(或on (name, ...)
) 可以使用,即。name
最左边的键在哪里。
为什么不把它设为最右边的键?例如。index on (name, deleted)
? 因为通常没有任何好处,只有当您想强制执行唯一约束时。只有 0 或 1 可供选择,一个index on (name)
或一个index on (name, deleted)
基本上提供相同的性能(如果它们可以使用的话)。将低选择性键放在左侧可启用某些范围扫描方案(例如WHERE type=5
)。
这不是一个好主意,因为索引的选择性会很低,并且因此而不是“加速”,这可能是一个缺点。
具有相同值的行越少,索引的选择性越好
在其他一些情况下,甚至全表扫描也可能更有效。
假设:您有 100 万行。那么第一个索引的选择性为:
(选择性=不同的值/行)
2 / 1.000.000 = 0,000002
在另一种情况下:
3 / 1.000.000 = 0,000003
这些值非常低!
或者以不同的方式:
估计选择性比 =(TotalRows / Distinct values)/ TotalRows * 100 = 1/Distinc 值 * 100。
在第一种情况下为 50%,在第二种情况下为 33%。
Sql server 的优化器不使用这个比率大于 15% 的索引。
(我的计算是一个简单的估计,但你可以在MSDN中找到统计信息)