【发布时间】:2010-10-11 04:40:57
【问题描述】:
您能解释一下微软 SQL Server 中覆盖索引和覆盖查询的概念以及它们之间的关系吗?
【问题讨论】:
标签: sql sql-server indexing
您能解释一下微软 SQL Server 中覆盖索引和覆盖查询的概念以及它们之间的关系吗?
【问题讨论】:
标签: sql sql-server indexing
覆盖索引是一种可以满足查询中所有请求的列而无需进一步查找聚集索引的索引。
没有覆盖查询这样的东西。
看看这篇 Simple-Talk 文章:Using Covering Indexes to Improve Query Performance。
【讨论】:
id, name, shop_id, price。如果您对shop_id, price 进行索引,那么您将涵盖计算商店 X 产品平均价格的查询,但您不会涵盖选择这些产品名称的查询,因为name 不是索引的一部分.
覆盖查询是关于可以使用基础表上的索引匹配所有谓词的位置。
这是提高正在考虑的 sql 性能的第一步。
【讨论】:
覆盖查询是一种查询,其中查询结果集中的所有列都是从非聚集索引中提取的。
一个查询通过索引的明智排列变成一个覆盖查询。
覆盖查询通常比非覆盖查询性能更高,部分原因是非聚集索引每页的行数比聚集索引或堆索引多,因此需要将更少的页面放入内存以满足查询.它们每页有更多行,因为只有部分表格行是索引行的一部分。
覆盖索引是在覆盖查询中使用的索引。没有索引本身就是覆盖索引这样的东西。一个索引可以是查询 A 的覆盖索引,同时又不是查询 B 的覆盖索引。
【讨论】:
LIMIT 1 查询确实没有从覆盖优化中受益? 在大多数情况下,获取一条记录只需要读取一个页面(忽略页外存储或非常宽的表等边缘情况)。即使是未涵盖的查询。
这是an article in devx.com,上面写着:
创建一个包含 SQL 查询中使用的所有列的非聚集索引,这种技术称为索引覆盖
我只能假设 覆盖查询 是一个具有覆盖其返回记录集中所有列的索引的查询。一个警告 - 必须构建索引和查询,以允许 SQL 服务器从查询中实际推断出索引是有用的。
例如,表自身的连接可能不会从此类索引中受益(取决于 SQL 查询执行计划器的智能):
PersonID ParentID Name
1 NULL Abe
2 NULL Bob
3 1 Carl
4 2 Dave
假设PersonID,ParentID,Name 上有一个索引 - 这将是一个查询的覆盖索引,例如:
SELECT PersonID, ParentID, Name FROM MyTable
但是这样的查询:
SELECT PersonID, Name FROM MyTable LEFT JOIN MyTable T ON T.PersonID=MyTable.ParentID
可能不会有太多好处,即使所有列都在索引中。为什么?因为您并没有真正告诉它您要使用PersonID,ParentID,Name 的三重索引。
相反,您正在构建基于两列的条件 - PersonID 和 ParentID(其中省略了 Name),然后您要求所有记录,包括 PersonID, Name 列。实际上,根据实施情况,索引可能会对后半部分有所帮助。但是对于第一部分,您最好使用其他索引。
【讨论】:
如果select查询列表中请求的所有列都在索引中可用,则查询引擎不必再次查找表这可以显着提高查询的性能。由于索引中所有请求的列都可用,因此索引覆盖了查询。因此,查询称为覆盖查询,索引为覆盖索引。
如果选择列表中的列来自同一个表,则聚集索引始终可以覆盖查询。
如果您不熟悉索引概念,以下链接可能会有所帮助:
【讨论】:
覆盖索引是提供每个所需列的索引,并且 SQL 服务器没有跳回聚集索引来查找任何列。这是通过使用非聚集索引和使用 INCLUDE 选项来覆盖列来实现的。 非键列只能包含在非聚集索引中。列不能同时在键列和 INCLUDE 列表中定义。 INCLUDE 列表中的列名不能重复。只有先删除非键索引后,才能从表中删除非键列。 Please see details here
【讨论】:
当我简单地回忆起聚集索引由已定义表中所有列的键排序非堆列表组成时,我的灯亮了。那么,“簇”这个词指的是所有列都有一个“簇”,就像那个“热点”中的一簇鱼一样。如果没有索引覆盖包含搜索值的列(等式的右侧),则执行计划使用聚簇索引搜索请求列的聚簇索引表示,因为它在任何其他列中都找不到请求的列“覆盖”指数。缺失将导致建议的执行计划中出现聚集索引查找运算符,其中查找的值在聚集索引表示的有序列表内的列内。
因此,一种解决方案是创建一个非聚集索引,该索引的列包含索引内的请求值。这样,就不需要引用聚集索引,优化器应该能够在执行计划中挂钩该索引而无需任何提示。但是,如果有一个 Predicate 命名单列集群键和一个参数到集群键上的标量值,则仍然使用集群索引查找运算符,即使在第二列上已经存在覆盖索引。没有索引的表。
【讨论】:
覆盖索引是Non-Clustered 索引。聚集索引和非聚集索引都使用 B-Tree 数据结构来改进对数据的搜索,不同之处在于,在聚集索引的叶子中,整条记录(即行)物理存储在那里!但这不是非聚集索引的情况。以下示例说明了这一点:
示例:我有一个包含三列的表:ID、Fname 和 Lname。
但是,对于非聚集索引,有两种可能性:表已经有聚集索引或者没有:
正如两个图表所示,此类非聚集索引不能提供良好的性能,因为它们无法仅从 B-Tree 中找到最喜欢的值(即 Lname)。相反,他们必须执行额外的查找步骤(Key 或 RID 查找)来查找 Lname 的值。而且,这是被覆盖的索引出现在屏幕上的地方。这里,ID 上的非聚集索引在 B-Tree 的叶子中覆盖了 Lname 旁边的值,因此不需要用于任何类型的查找。
【讨论】:
第 178 页,高性能 MySQL,第 3 版
包含(或“覆盖”)满足查询所需的所有数据的索引称为覆盖索引。
当您发出一个被索引覆盖的查询(一个被索引覆盖的查询)时,您会在 EXPLAIN 的 Extra 列中看到“Using Index”。
【讨论】: