簡體   English   中英

使用復合聚簇索引時,SQL Server是否會跳槽?

[英]Does SQL Server jump leaves when using a composite clustered index?

請考慮以下復合聚簇索引:

CREATE UNIQUE CLUSTERED INDEX ix_mytable ON mytable(a, b)

顯然,基於B獨立指數將尋求更快B的特定值。

但是,如果沒有使用b上的單獨索引,在我看來,復合索引仍可用於通過遍歷a和離散值的樹來查找具有b的特定值而不是表掃描的元組。對於b本地搜索,跳轉到 ,等下一個值

這是SQL Server的工作原理嗎? (例如,如果MSSQL對具有多列的索引使用單個哈希值,則不會這樣。)

它是,並且由於其他原因已經需要復合索引,並且a的離散值的數量足夠小,性能/空間權衡可能擺脫具有b的單獨索引。

(以上UNIQUE和集群約束不是真正需要對於這個例子,但它們將代表B的最快的檢索不涉及一個單獨的索引對於b --the前者提供的快捷方式每個環路,后者除去查找中的一個間接度)。

不,沒有跳過'a'的集群。 只有在指定了最左邊的列時才能使用索引,否則需要使用完整掃描。

Oracle擁有所謂的“Index Skip Scan”運算符。

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;
GO

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM