З огляду на просте приєднання трьох таблиць, продуктивність запитів різко змінюється, коли ORDER BY включений навіть без повернення рядків. Справжній сценарій проблеми займає 30 секунд, щоб повернути нульові рядки, але миттєвий, коли ЗАМОВЛЕННЯ ВНЕ включено. Чому?
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 */
Я розумію, що я міг би мати індекс на bigtable.smallGuidId, але, я вважаю, це насправді погіршило б у цьому випадку.
Ось сценарій для створення / заповнення таблиць для тесту. Цікаво, що, мабуть, має значення те, що в маленькому таблицю є поле nvarchar (max). Також, мабуть, має значення те, що я приєднуюся до великого столу з орієнтиром (який, мабуть, змушує використовувати хеш-відповідність).
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
Я тестував на SQL 2005, 2008 та 2008R2 з однаковими результатами.