统计数据(有助于决定是否使用索引)会考虑每实际列值的行数,还是只使用平均值每个值的行数。
假设我有一个名为active的位列的表,它有一百万行,但99.99%设置为false。如果我在这个列上有一个索引,那么Sql足够智能,如果搜索active = 1就知道使用索引但是如果搜索active = 0则没有意义。
另一个例子,如果我有一个表,其中包含一个索引列的1,000,000条记录,其中包含大约50,000个不同的值,每个值的平均行数为10,但是有一个特殊值,其中包含500,000行。如果搜索此特殊记录,索引可能没用,但在查找任何其他代码时非常有用。
但这种特殊情况是否会破坏指数的有效性。
答案 0 :(得分:3)
你可以亲眼看看:
CREATE TABLE IndexTest (
Id int not null primary key identity(1,1),
Active bit not null default(0),
IndexedValue nvarchar(10) not null
)
CREATE INDEX IndexTestActive ON IndexTest (Active)
CREATE INDEX IndexTestIndexedValue ON IndexTest (IndexedValue)
DECLARE @values table
(
Id int primary key IDENTITY(1, 1),
Value nvarchar(10)
)
INSERT INTO @values(Value) VALUES ('1')
INSERT INTO @values(Value) VALUES ('2')
INSERT INTO @values(Value) VALUES ('3')
INSERT INTO @values(Value) VALUES ('4')
INSERT INTO @values(Value) VALUES ('5')
INSERT INTO @values(Value) VALUES ('Many')
INSERT INTO @values(Value) VALUES ('Many')
INSERT INTO @values(Value) VALUES ('Many')
INSERT INTO @values(Value) VALUES ('Many')
INSERT INTO @values(Value) VALUES ('Many')
DECLARE @rowCount int
SET @rowCount = 100000
WHILE(@rowCount > 0)
BEGIN
DECLARE @valueIndex int
SET @valueIndex = CAST(RAND() * 10 + 1 as int)
DECLARE @selectedValue nvarchar(10)
SELECT @selectedValue = Value FROM @values WHERE Id = @valueIndex
DECLARE @isActive bit
SELECT @isActive = CASE
WHEN RAND() < 0.001 THEN 1
ELSE 0
END
INSERT INTO IndexTest(Active, IndexedValue) VALUES (@isActive, @selectedValue)
SET @rowCount = @rowCount - 1
END
SELECT count(*) FROM IndexTest WHERE Active = 1
SELECT count(*) FROM IndexTest WHERE Active = 0
SELECT count(*) FROM IndexTest WHERE IndexedValue = '1'
SELECT count(*) FROM IndexTest WHERE IndexedValue = 'Many'
在我看来它总是使用此查询计划中的索引:
答案 1 :(得分:1)
它会创建一个直方图,然后使用它。
使用位列,可以很好地了解有多少是0和1
对于一个字符串列,它会大致了解“band”(值a,b,c等)。数字相同(它创建x范围的值范围)。
只需查看统计信息在管理工作室中的外观 - 您实际上可以访问直方图。
答案 2 :(得分:1)
您只需查看统计信息并亲眼看看:) DBCC SHOW_STATISTICS
。请参阅备注部分,它对如何实际存储和使用直方图有一个很好的解释:
创建直方图,查询 优化器对列值进行排序, 计算值的数量 匹配每个不同的列值和 然后将列值聚合到 最多200个连续直方图 脚步。每一步都包括一系列 列值后跟上部 绑定列值。范围包括 所有可能的列值之间 边界值,不包括 边界值本身。最低的 已排序的列值是 第一个上限值 直方图步骤。
对于每个直方图步骤:
- 粗线表示上边界值(RANGE_HI_KEY)和 它发生的次数(EQ_ROWS)
- RANGE_HI_KEY左侧的实线区域表示列值的范围 和每个的平均次数 发生列值(AVG_RANGE_ROWS)。 第一个AVG_RANGE_ROWS 直方图步长始终为0.
- 虚线表示用于估算总数的采样值 范围内的不同值的数量 (DISTINCT_RANGE_ROWS)和总数 范围内的值(RANGE_ROWS)。 查询优化器使用RANGE_ROWS 和DISTINCT_RANGE_ROWS来计算 AVG_RANGE_ROWS并且不存储 采样值。
查询优化器定义了 根据他们的直方图步骤 统计学意义。它使用了 最大差分算法 最小化步骤数 直方图,同时最大化 边界之间的差异 值。最大步数是 200.直方图步骤的数量可以少于不同的数量 值,即使是较少的列 超过200个边界点。例如, 具有100个不同值的列可以 有一个小于100的直方图 边界点。