sql-server - SQL索引查找

标签 sql-server sql-server-2005 indexing

查询发生了一件奇怪的事情。我有一个包含两个bigints的表StartNum和EndNum,用于定义数字范围。我在这两列上都有一个索引。该查询采用给定的数字,并返回其所属的范围。 WHERE子句是where @Num >= StartNum and @Num <= EndNum

在探查器中,搜索列表开头附近的数字和结尾附近的数字之间存在很大差异。该数字在列表中越靠后,则需要的读取次数和持续时间就越多。查询计划表明它正在对我的索引使用搜索。

因为索引是一棵平衡的树,所以肯定不会有太大的差异。有人可以向我解释一下吗?

小字:
这是在SQL 2005 Workgoup版本上。表中大约有200,000行。索引是非聚簇的(聚簇索引在标识列上,但是数据以StartNum顺序插入)。索引有716页,深度为3,碎片为3%。

最佳答案

这取决于您的查询。如果仅查询这两个值,例如:

SELECT StartNum, EndNum
FROM Books
WHERE (@Num >= StartNum) AND (@Num <= EndNum)


在这种情况下,SQL Server只需搜索两个索引即可返回数字。您的两个索引包含您被索引的值,并且因为这是一个索引,所以它们被排序了。

但我确定您实际上在查询中包括其他列:

SELECT BookID, Title, IDBN, Author, StartNum, EndNum
FROM Books
WHERE (@Num >= StartNum) AND (@Num <= EndNum)


在这种情况下,SQL Server一旦找到与条件匹配的行的ID,就必须返回数据库并找到这些行,以便它可以为您返回:


标题
书号
作者


除了已经从两个索引中获得的值之外:


StartNum
EndNum
书号


注意:StartNum上的索引隐式包含聚集键的值,因为这是它知道与索引中的条目相对应的行的方式。

问题是,如果必须在表中查找“太多书”,那么从上到下阅读整个表可能会更快。



打个比方:您可以在书的索引中查找对“设计模式”的所有引用。


设计模式:4、89、221、442


如果只有4个条目,则可以倒向索引中列出的页面。这称为书签查找。

但是,如果索引显示有827个短语引用该怎么办?


计算机:1、2、6 [剪切825个条目],1087、1128


然后,通读本书以自行找到它们可能会更快。在这种情况下,我们放弃并扫描整本书。如果表具有聚集索引,则SQL Server将此称为聚集索引扫描,如果没有聚集索引,则称为表扫描(即,这是“堆表”)



如果您只是在查询中引用StartNum和EndNum(假设您正在计数),那么我敢肯定,您将始终看到较低的读取次数和执行时间。但是,如果您包括其他列,并且SQL Server认为该查询将返回太多行(例如,超过表的5%),那么它将忘记索引并扫描整个表表。

有一个交叉点,SQL Server知道表中StartNum和EndNum值的分布,因为它会采样值并对它们的分布进行统计。如果@Num的某些值恰好返回几行,并且SQL Server知道这一点,它将执行相对较少的书签查找。但是,如果您的数据分发将导致更多行返回,那么您将获得聚集索引扫描。

关于sql-server - SQL索引查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/956346/

相关文章:

sql-server-2005 - 在SQL Server 2005中如何舍入没有尾随零?

PostgreSQL 9.2 : GIN Index on citext[]

SQL 触发器无法正常工作

sql-server - 将子查询中的多个结果合并为单个逗号分隔值

sql-server - SQLAlchemy 和 mssql : how to create unique constraint with multiple null value

mysql - 如何确定在 MySQL 表中索引的内容

indexing - 在PANDAS中,如何获取已知值的索引?

sql - 如何使用 sql case 语句重新创建此逻辑

SQL Server 2005 - 多处理器使用

sql-server-2005 - 多对多关系中的查询示例