Я ожидаю, что эти два SELECT
будут иметь одинаковый план выполнения и производительность. Поскольку в LIKE
есть начальный подстановочный знак, я ожидаю сканирования индекса. Когда я запускаю это и смотрю планы, первый SELECT
ведет себя как положено (со сканированием). Но второй план SELECT
показывает поиск по индексу и работает в 20 раз быстрее.
Код:
-- Uses index scan, as expected:
SELECT 1
FROM AccountAction
WHERE AccountNumber LIKE '%441025586401'
-- Uses index seek somehow, and runs much faster:
declare @empty VARCHAR(30) = ''
SELECT 1
FROM AccountAction
WHERE AccountNumber LIKE '%441025586401' + @empty
Вопрос:
Как SQL Server использует поиск по индексу, если шаблон начинается с подстановочного знака?
Бонусный вопрос:
Почему объединение пустой строки изменяет/улучшает план выполнения?
Подробности:
- На
Accounts.AccountNumber
есть некластеризованный индекс - Есть и другие индексы, но и поиск, и сканирование выполняются по этому индексу.
- Столбец
Accounts.AccountNumber
является обнуляемымvarchar(30)
- Сервер SQL Server 2012.
Определения таблиц и указателей:
CREATE TABLE [updatable].[AccountAction](
[ID] [int] IDENTITY(1,1) NOT NULL,
[AccountNumber] [varchar](30) NULL,
[Utility] [varchar](9) NOT NULL,
[SomeData1] [varchar](10) NOT NULL,
[SomeData2] [varchar](200) NULL,
[SomeData3] [money] NULL,
--...
[Created] [datetime] NULL,
CONSTRAINT [PK_Account] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [IX_updatable_AccountAction_AccountNumber_UtilityCode_ActionTypeCd] ON [updatable].[AccountAction]
(
[AccountNumber] ASC,
[Utility] ASC
)
INCLUDE ([SomeData1], [SomeData2], [SomeData3]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
CREATE CLUSTERED INDEX [CIX_Account] ON [updatable].[AccountAction]
(
[Created] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
ПРИМЕЧАНИЕ. Вот фактический план выполнения двух запросов. Имена объектов немного отличаются от приведенного выше кода, потому что я пытался упростить вопрос.
LIKE '%441025586401%'
с подстановочным знаком в начале и в конце. - person Lamak   schedule 06.08.2013OPTION (RECOMPILE)
в запросе (или очистите кэш планов)? - person Aaron Bertrand   schedule 06.08.2013SET STATISTICS TIME ON;
иSET STATISTICS IO ON;
, чтобы увидеть, что на самом деле лучше: поиск или сканирование. Не полагайтесь только на цифры 96 % и 4 %, чтобы получить какое-либо представление о фактической производительности — эти цифры сами по себе в значительной степени бессмысленны. - person Aaron Bertrand   schedule 06.08.2013OPTION (RECOMPILE)
? - person swasheck   schedule 06.08.2013