Sql server 2008 这个复合索引会帮助所有这些查询吗?

Sql server 2008 这个复合索引会帮助所有这些查询吗?,sql-server-2008,tsql,indexing,Sql Server 2008,Tsql,Indexing,假设我有下表: Orders ====== OrderID CustomerID StatusID DateCreated 我有以下疑问: select CustomerID from Orders where OrderID = 100 select OrderID from Orders where CustomerID = 20 select OrderID, StatusID from Orders where CustomerID = 100 and OrderID = 1000

假设我有下表:

Orders
======
OrderID
CustomerID
StatusID
DateCreated
我有以下疑问:

select CustomerID from Orders where OrderID = 100

select OrderID from Orders where CustomerID = 20

select OrderID, StatusID from Orders where CustomerID = 100 and OrderID = 1000
如果我制作以下索引:

create nonclustered index Example
  On dbo.Orders(OrderID,CustomerID)
  Include(StatusID)

这是否考虑了使用一个索引对所有3个查询进行优化?换句话说,复合索引是否改善了使用复合索引中某个项的查询?或者,为了满足查询1和查询2,是否也应该在这些列(即OrderID、CustomerID)上创建单独的索引?

此索引对第二个查询没有帮助,因为无法首先在索引中最左边的列上搜索

想想电话簿吧。首先,试着找到所有姓史密斯的人。简单,对吗?现在,试着找到所有名字叫约翰的人。电话簿中“索引”的工作方式是LastName,FirstName。当你试图找到所有的约翰时,让他们先按姓氏排序一点帮助都没有——你仍然需要查看整个电话簿,因为会有一个约翰·安德森和一个约翰·佐尔蒂以及介于两者之间的一切

为了充分利用这三个查询,并假设这是目前使用的仅有的三个查询表单,我可能会建议添加一个索引:

create nonclustered index Example2
  On dbo.Orders(CustomerID) INCLUDE(OrderID)
(如果OrderID是主键,则不需要包含它。)

但是,这应该针对您的工作负载进行测试,因为索引不是空闲的——它们确实需要额外的磁盘空间,并且在运行DML查询时需要维护额外的工作。同样,这假设问题中列出的三个查询是您使用的唯一形状。如果您有其他具有不同输出列或不同where子句的查询,则所有下注都将被取消

create nonclustered index Example
  On dbo.Orders(OrderID,CustomerID)
  Include(StatusID)
将此索引读取为:从Orders表创建OrderID、CustomerID、StatusID的系统维护副本。按OrderID订购此副本并断开与CustomerID的联系

select CustomerID from Orders where OrderID = 100
由于索引是按OrderID排序的,因此查找第一条符合条件的记录很快。找到第一条记录后,我们可以继续读取索引,直到找到OrderID不是100的记录。然后我们可以停下来。因为我们想要的所有列都在索引中,所以我们不必查找实际的表。太好了

select OrderID from Orders where CustomerID = 20
由于索引是按OrderID然后按CustomerID排序的,因此符合条件的记录可能会出现在索引中的任何位置。第一条记录可能符合条件(OrderID=1,CustomerID=20)。最后一条记录可能符合条件(OrderID=100000000,CustomerID=20)。我们必须阅读整个索引才能找到符合条件的记录这很糟糕。一个小帮助:因为我们想要的所有列都在索引中,所以我们不必查找实际的表。因此,从技术上讲,第二个查询是由索引来帮助的——只是没有达到其他查询得到帮助的程度

select OrderID, StatusID from Orders where CustomerID = 100 and OrderID = 1000 
因为索引是按OrderID然后按CustomerID排序的,所以查找第一条符合条件的记录很快。一旦找到第一条记录,我们就可以继续读取索引,直到找到不符合条件的记录。然后我们可以停下来。因为我们想要的所有列都在索引中,所以我们不必查找实际的表。太好了

select OrderID from Orders where CustomerID = 20

复合索引是否改进了使用复合索引中某个项的查询

有时候

或者,为了满足查询1和查询2,是否也应该在这些列(即OrderID、CustomerID)上创建单独的索引

有时候不是

真正的答案是微妙的,因为索引声明中列的顺序决定了索引中记录的顺序。一些查询通过某些排序得到帮助,而其他查询则没有。您可能需要用一个以上的索引来补充当前索引,以涵盖CustomerID、OrderID案例


“因为我们想要的所有列都在索引中,所以我们不必查找实际的表”--所以索引可以用于读取目的,尽管不用于查找/查找目的


当索引(表的一部分的副本)包含解析查询所需的所有信息时,不需要读取实际的表。索引“覆盖”了查询。

以上答案是正确的。但他们遗漏了一件事。您可能需要ORDER_ID上的聚集索引。如果您在ORDER_ID上创建聚集索引,则表上的任何非聚集索引都将自动包含该值,因为非聚集索引项指向存在聚集索引的表上的聚集索引。所以你想要这个:

create clustered index IX_ORDERS_ORDERID on ORDERS (OrderID)
go
create nonclustered index IX_ORDERS_CustomerID
On dbo.Orders(CustomerID)
Include(StatusID)
go

现在,您可以快速搜索订单id或客户id,所有查询都可以正常运行。你知道怎么看执行计划吗?在sql studio中,转到查询-包括实际执行计划,然后运行查询。您将看到使用了哪些索引的图形表示,是否执行了搜索或扫描等。

请其中一位对下面的部分进行评论--“因为我们需要的所有列都在索引中,所以我们不必查找实际的表”--因此,该索引可以用于读取目的,但不用于查找/查找目的?是的,@Micah,如果该列位于索引中(键的一部分或作为包含列),则它可以阻止对聚集索引/堆进行查找。这可能有助于提高性能,但对整个表/索引的扫描仍然是一次完整的扫描,在大多数情况下,这两个差异的大小相当大。当然,你可以用你的结构、数据、硬件等来测试这些东西。。。