У меня есть структура базы данных, похожая на эту,
CREATE TABLE [dbo].[Dispatch](
[DispatchId] [int] NOT NULL,
[ContractId] [int] NOT NULL,
[DispatchDescription] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Dispatch] PRIMARY KEY CLUSTERED
(
[DispatchId] ASC,
[ContractId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[DispatchLink](
[ContractLink1] [int] NOT NULL,
[DispatchLink1] [int] NOT NULL,
[ContractLink2] [int] NOT NULL,
[DispatchLink2] [int] NOT NULL
) ON [PRIMARY]
GO
INSERT [dbo].[Dispatch] ([DispatchId], [ContractId], [DispatchDescription]) VALUES (1, 1, N'Test')
GO
INSERT [dbo].[Dispatch] ([DispatchId], [ContractId], [DispatchDescription]) VALUES (2, 1, N'Test')
GO
INSERT [dbo].[Dispatch] ([DispatchId], [ContractId], [DispatchDescription]) VALUES (3, 1, N'Test')
GO
INSERT [dbo].[Dispatch] ([DispatchId], [ContractId], [DispatchDescription]) VALUES (4, 1, N'Test')
GO
INSERT [dbo].[DispatchLink] ([ContractLink1], [DispatchLink1], [ContractLink2], [DispatchLink2]) VALUES (1, 1, 1, 2)
GO
INSERT [dbo].[DispatchLink] ([ContractLink1], [DispatchLink1], [ContractLink2], [DispatchLink2]) VALUES (1, 1, 1, 3)
GO
INSERT [dbo].[DispatchLink] ([ContractLink1], [DispatchLink1], [ContractLink2], [DispatchLink2]) VALUES (1, 3, 1, 2)
GO
Задача таблицы DispatchLink - связать две записи Dispatch вместе. Между прочим, я использую составной первичный ключ в своей таблице диспетчеризации из-за устаревшего, поэтому я не могу изменить это без большой боли. Также таблица ссылок не может быть правильным способом сделать это? Но опять наследие.
Так что мой вопрос, если я выполню этот запрос
select * from Dispatch d
inner join DispatchLink dl on d.DispatchId = dl.DispatchLink1 and d.ContractId = dl.ContractLink1
or d.DispatchId = dl.DispatchLink2 and d.ContractId = dl.ContractLink2
Я никогда не смогу выполнить поиск индекса по таблице DispatchLink. Всегда выполняется полное сканирование индекса. Это хорошо с несколькими записями, но когда у вас есть 50000 в этой таблице, она сканирует 50000 записей в индексе в соответствии с планом запроса. Это потому, что в предложении объединения есть «ands» и «ors», но я не могу понять, почему SQL не может вместо этого выполнить пару поисков индекса, один для левой части «or», и один для правой стороны «или».
Я хотел бы получить объяснение этому, а не предложение ускорить запрос, если это не может быть сделано без корректировки запроса. Причина в том, что я использую приведенный выше запрос в качестве фильтра объединения репликации слиянием, поэтому, к сожалению, я не могу просто добавить другой тип запроса.
ОБНОВЛЕНИЕ: Например, это типы индексов, которые я добавил,
CREATE NONCLUSTERED INDEX IDX1 ON DispatchLink (ContractLink1, DispatchLink1)
CREATE NONCLUSTERED INDEX IDX2 ON DispatchLink (ContractLink2, DispatchLink2)
CREATE NONCLUSTERED INDEX IDX3 ON DispatchLink (ContractLink1, DispatchLink1, ContractLink2, DispatchLink2)
Таким образом, он использует индексы, но выполняет сканирование индекса по всему индексу, поэтому 50000 записей сканирует 50000 записей в индексе.
DispatchLink
столе?