Étant donné une simple jointure à trois tables, les performances des requêtes changent radicalement lorsque ORDER BY est inclus, même si aucune ligne n'est renvoyée. Le scénario de problème réel prend 30 secondes pour retourner zéro ligne mais est instantané lorsque ORDER BY n'est pas inclus. Pourquoi?
SELECT *
FROM tinytable t /* one narrow row */
JOIN smalltable s on t.id=s.tinyId /* one narrow row */
JOIN bigtable b on b.smallGuidId=s.GuidId /* a million narrow rows */
WHERE t.foreignId=3 /* doesn't match */
ORDER BY b.CreatedUtc /* try with and without this ORDER BY */
Je comprends que je pourrais avoir un index sur bigtable.smallGuidId, mais, je crois que cela aggraverait en fait dans ce cas.
Voici un script pour créer / remplir les tables à tester. Curieusement, il semble important que smalltable ait un champ nvarchar (max). Il semble également important que je me joigne à la bigtable avec un guid (ce qui donne l'impression d'utiliser la correspondance de hachage).
CREATE TABLE tinytable
(
id INT PRIMARY KEY IDENTITY(1, 1),
foreignId INT NOT NULL
)
CREATE TABLE smalltable
(
id INT PRIMARY KEY IDENTITY(1, 1),
GuidId UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID(),
tinyId INT NOT NULL,
Magic NVARCHAR(max) NOT NULL DEFAULT ''
)
CREATE TABLE bigtable
(
id INT PRIMARY KEY IDENTITY(1, 1),
CreatedUtc DATETIME NOT NULL DEFAULT GETUTCDATE(),
smallGuidId UNIQUEIDENTIFIER NOT NULL
)
INSERT tinytable
(foreignId)
VALUES(7)
INSERT smalltable
(tinyId)
VALUES(1)
-- make a million rows
DECLARE @i INT;
SET @i=20;
INSERT bigtable
(smallGuidId)
SELECT GuidId
FROM smalltable;
WHILE @i > 0
BEGIN
INSERT bigtable
(smallGuidId)
SELECT smallGuidId
FROM bigtable;
SET @i=@i - 1;
END
J'ai testé sur SQL 2005, 2008 et 2008R2 avec les mêmes résultats.