考虑以下复合聚集索引:
CREATE UNIQUE CLUSTERED INDEX ix_mytable ON mytable(a, b)显然,b上的单独索引将使搜索特定值b的速度加快。
但是,如果b上的单独索引是而不是,那么在我看来,复合索引仍然可以用于查找具有特定值的元组,而不是表扫描,方法是遍历a的离散值树,对b进行局部搜索,跳转到a的下一个值,等等。
这就是Server的工作方式吗?(例如,如果MSSQL对具有多列的索引使用单个哈希值,则不会发生这种情况。)
是的,而且由于其他原因已经需要综合指数,而且a的离散值的数目足够小,性能/空间的权衡可能会偏离对b的单独的指数。
(本例并不真正需要上面的唯一和聚集约束,但它们表示的是不涉及b的单独索引的b的最快检索--前者为a的每个循环提供了一个快捷方式,后者在查找中消除了某种程度的间接搜索)。
发布于 2009-10-23 21:14:58
不,没有跳过一团'a‘。只有在指定了最左边的列时,才能使用索引,否则需要使用完整的扫描。
Oracle有所谓的“索引跳过扫描”运算符。
发布于 2013-07-11 15:15:14
USE AdventureWorks2008R2;
-- Source: http://msftdbprodsamples.codeplex.com/releases/view/59211
GO
SET NOCOUNT ON;
GO
CREATE NONCLUSTERED INDEX IX_SalesOrderHeader_OrderDate_#_ShipDate_SubTotal
ON [Sales].[SalesOrderHeader] ([OrderDate])
INCLUDE (ShipDate,SubTotal)
-- WITH(DROP_EXISTING=ON);
GO
-- Test 1
SET STATISTICS IO ON;
SELECT COUNT(*)
FROM Sales.SalesOrderHeader h -- Index Seek on IX_SalesOrderHeader_OrderDate_#_ShipDate_SubTotal
WHERE h.OrderDate BETWEEN '2008-07-01T00:00:00.000' AND '2008-07-15T23:59:59.997';
SET STATISTICS IO OFF;
GO
-- End of Test 1
-- Results:
-- Table 'SalesOrderHeader'. Scan count 1, logical reads 5, physical reads 0
DROP INDEX IX_SalesOrderHeader_OrderDate_#_ShipDate_SubTotal
ON [Sales].[SalesOrderHeader]
GO
CREATE NONCLUSTERED INDEX [IX_SalesOrderHeader_ShipMethodID_OrderDate_#_ShipDate_SubTotal]
ON Sales.SalesOrderHeader
(
ShipMethodID ASC,
OrderDate ASC
)
INCLUDE (ShipDate,SubTotal);
GO
-- Test 2
SET STATISTICS IO ON;
SELECT COUNT(*)
FROM Sales.SalesOrderHeader h -- Index Scan on IX_SalesOrderHeader_ShipMethodID_OrderDate_#_ShipDate_SubTotal
WHERE h.OrderDate BETWEEN '2008-07-01T00:00:00.000' AND '2008-07-15T23:59:59.997';
SET STATISTICS IO OFF;
GO
-- End of Test 2
-- Results:
-- Table 'SalesOrderHeader'. Scan count 1, logical reads 150, physical reads 0
-- Test 3
SET STATISTICS IO ON;
SELECT COUNT(*)
FROM Purchasing.ShipMethod sm
INNER JOIN Sales.SalesOrderHeader h ON h.ShipMethodID=sm.ShipMethodID -- FK elimination + Index Scan on IX_SalesOrderHeader_ShipMethodID_OrderDate_#_ShipDate_SubTotal
WHERE h.OrderDate BETWEEN '2008-07-01T00:00:00.000' AND '2008-07-15T23:59:59.997';
SET STATISTICS IO OFF;
GO
-- End of Test 3
-- Results:
-- Table 'SalesOrderHeader'. Scan count 1, logical reads 150, physical reads 0
-- Test 4
SET STATISTICS IO ON;
SELECT MIN(sm.ShipMethodID) AS DummnyCol, -- To prevent FK elimination
COUNT(*)
FROM Purchasing.ShipMethod sm
INNER JOIN Sales.SalesOrderHeader h ON h.ShipMethodID=sm.ShipMethodID -- Index Seek on IX_SalesOrderHeader_ShipMethodID_OrderDate_#_ShipDate_SubTotal
WHERE h.OrderDate BETWEEN '2008-07-01T00:00:00.000' AND '2008-07-15T23:59:59.997';
SET STATISTICS IO OFF;
GO
-- End of Test 4
-- Results:
-- Table 'SalesOrderHeader'. Scan count 5, logical reads 13, physical reads 0
-- Table 'ShipMethod'. Scan count 1, logical reads 2, physical reads 0
DROP INDEX [IX_SalesOrderHeader_ShipMethodID_OrderDate_#_ShipDate_SubTotal]
ON Sales.SalesOrderHeader;
GO
SET NOCOUNT OFF;
GOhttps://stackoverflow.com/questions/1615893
复制相似问题