Biorąc pod uwagę proste łączenie trzech tabel, wydajność zapytania zmienia się drastycznie, gdy ORDER BY jest uwzględniony, nawet bez zwracania wierszy. Rzeczywisty scenariusz problemu zajmuje 30 sekund, aby zwrócić zero wierszy, ale jest natychmiastowy, gdy nie uwzględniono ORDER BY. Dlaczego?
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 */
Rozumiem, że mógłbym mieć indeks na bigtable.smallGuidId, ale wierzę, że tak naprawdę pogorszyłoby to sytuację w tym przypadku.
Oto skrypt do tworzenia / wypełniania tabel do testowania. Co ciekawe, wydaje się mieć znaczenie, że smalltable ma pole nvarchar (max). Wydaje się również mieć znaczenie, że dołączam do bigtable z przewodnikiem (co, jak sądzę, sprawia, że chce używać dopasowywania skrótów).
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
Testowałem na SQL 2005, 2008 i 2008R2 z tymi samymi wynikami.