Я намагаюся зрозуміти, чому використання змінної таблиці забороняє оптимізатору використовувати пошук індексів, а потім шукати закладку порівняно зі скануванням індексу.
Наповнення таблиці:
CREATE TABLE dbo.Test
(
RowKey INT NOT NULL PRIMARY KEY,
SecondColumn CHAR(1) NOT NULL DEFAULT 'x',
ForeignKey INT NOT NULL
)
INSERT dbo.Test
(
RowKey,
ForeignKey
)
SELECT TOP 1000000
ROW_NUMBER() OVER (ORDER BY (SELECT 0)),
ABS(CHECKSUM(NEWID()) % 10)
FROM sys.all_objects s1
CROSS JOIN sys.all_objects s2
CREATE INDEX ix_Test_1 ON dbo.Test (ForeignKey)
Наповніть змінну таблиці за допомогою одного запису та спробуйте знайти первинний ключ та другий стовпець шляхом пошуку в стовпці із зовнішнім ключем:
DECLARE @Keys TABLE (RowKey INT NOT NULL)
INSERT @Keys (RowKey) VALUES (10)
SELECT
t.RowKey,
t.SecondColumn
FROM
dbo.Test t
INNER JOIN
@Keys k
ON
t.ForeignKey = k.RowKey
Нижче наведено план виконання:
Тепер той самий запит, використовуючи замість таблиці темп:
CREATE TABLE #Keys (RowKey INT NOT NULL)
INSERT #Keys (RowKey) VALUES (10)
SELECT
t.RowKey,
t.SecondColumn
FROM
dbo.Test t
INNER JOIN
#Keys k
ON
t.ForeignKey = k.RowKey
Цей план запитів використовує пошук пошуку та закладки:
Чому оптимізатор готовий шукати закладки за допомогою таблиці temp, але не змінною таблиці?
Таблиця змінної використовується в цьому прикладі для представлення даних, що надходять через визначений користувачем тип таблиці в збереженій процедурі.
Я усвідомлюю, що пошук індексу може бути невідповідним, якщо значення іноземного ключа траплялося сотні тисяч разів. У цьому випадку сканування, ймовірно, буде кращим вибором. Для створеного мною сценарію не було рядка зі значенням 10. Я все ще думаю, що поведінка цікава, і хотілося б знати, чи є в ній причина.
Додавання OPTION (RECOMPILE)
не змінило поведінку. У UDDT є первинний ключ.
@@VERSION
є SQL Server 2008 R2 (SP2) - 10.50.4042.0 (X64) (збірка 7601: пакет оновлень 1) (Hypervisor)