Question

Considérez l'index en cluster composite suivant:

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

Évidemment, un index séparé sur b accélérera la recherche d'une valeur particulière de b .

Cependant, si un index séparé sur b n'est pas utilisé , il me semble que l'index composite peut toujours être utilisé pour rechercher des n-uplets avec une valeur particulière pour < em> b au lieu d’un balayage de table, en parcourant l’arbre des valeurs discrètes de a et en effectuant une recherche locale de b , passez à la valeur suivante de a , etc.

Est-ce la façon dont fonctionne SQL Server? (Ce ne serait pas le cas, par exemple, si MSSQL utilise une seule valeur de hachage pour les index à plusieurs colonnes.)

C’est vrai, et l’indice composite est déjà nécessaire pour d’autres raisons, et comme le nombre de valeurs discrètes de a est suffisamment petit, le compromis performances / espace risque de ne plus avoir index séparé pour b .

(Les contraintes UNIQUE et CLUSTERED ci-dessus ne sont pas vraiment nécessaires pour cet exemple, mais elles représenteraient l'extraction la plus rapide de b qui ne comportait pas d'index séparé pour b - le premier fournissant un raccourci pour chaque boucle de a , le dernier supprimant un degré d'indirection dans la recherche).

Était-ce utile?

La solution

Non, il est impossible de sauter par-dessus un groupe de "a". Un index ne peut être utilisé que si la colonne la plus à gauche est spécifiée, sinon une analyse complète doit être utilisée.

Oracle utilise le "Index Skip Scan" . opérateur.

Autres conseils

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top