Dato un semplice join a tre tabelle, le prestazioni della query cambiano drasticamente quando ORDER BY è incluso anche senza restituire righe. Lo scenario del problema effettivo impiega 30 secondi per restituire zero righe ma è istantaneo quando ORDER BY non è incluso. Perché?
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 */
Capisco che avrei potuto avere un indice su bigtable.smallGuidId, ma credo che in questo caso peggiorerebbe la situazione.
Ecco lo script per creare / popolare le tabelle per il test. Curiosamente, sembra importare che il smalltable abbia un campo nvarchar (max). Sembra anche che mi unisca al bigtable con un guid (che immagino gli faccia venir voglia di usare l'hash matching).
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
Ho provato su SQL 2005, 2008 e 2008R2 con gli stessi risultati.