Voici une question qui m'a intrigué au moment où je rédigeais mes articles sur SQL Server. J'ai posé la question sur le forum MSDN, mais je n'ai pas obtenu de réponse satisfaisante, je profite donc des experts SQL Server du réseau codes-sources pour peut être avoir une réponse à cette question.
Créons d'abord une table :
CREATE TABLE dbo.Persons
(
Id int NOT NULL IDENTITY (1, 1),
FirstName varchar(50) NOT NULL,
LastName varchar(50) NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE dbo.Persons ADD CONSTRAINT
PK_Persons PRIMARY KEY CLUSTERED (Id) ON [PRIMARY]
GO
Insérons ensuite 5000 enregistrements :
INSERT INTO [dbo].[Persons] (FirstName, LastName) VALUES ('First name', 'Last name')
GO 5000
Consultons ensuite les DMV pour connaître le nombre de pages dans le clustered index :
SELECT * FROM sys.dm_db_index_physical_stats (db_id(), object_id('dbo.MyTable'), null, null, 'DETAILED')
Le résultat dans mon cas est le suivant :
| index_type_desc |
index_depth |
index_level |
page_count |
record_count |
CLUSTERED INDEX
|
2
|
0
|
24
|
5000
|
CLUSTERED INDEX
|
2
|
1
|
1
|
24
|
Nous avons donc un clustered index à deux niveaux. Le niveau racine a bien entendu une page, et 24 entrées correspondantes chacune à une page du niveau suivant, puisque le second niveau a 24 pages.
Exécutons ensuite la requête suivante avec les statistiques IO activées :
SELECT * FROM [dbo].[Persons]
Les statistiques indiquent :
Table 'Persons'. Scan count 1, logical reads 26, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Un scan est normalement effectué de la façon suivante : la page racine va être lue de façon à localiser la première page du niveau terminal de l'index, puis toutes les pages sont scannées dans l'ordre. On devrait donc avoir un logical read pour la racine, puis 24 pour le niveau terminal, donc 25 reads au total.
Avec la requête suivante :
SELECT TOP(50) * FROM [dbo].[Persons]
Seulement 2 pages sont lues (la racine, puis la première page du niveau terminal) :
Table 'Persons'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
J'obtiens donc ce que j'attendais.
Ma question est donc : pourquoi est-ce que dans le premier cas, on observe un 26e read ?