У мене структура бази даних схожа на цю,
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 не може замість цього здійснити пару пошукових індексів, один для лівого боку "або", і один для правого боку 'або'.
Я б хотів пояснити це, а не пропозицію зробити запит швидше, якщо це не можна зробити без коригування запиту. Причина полягає в тому, що я використовую вищезазначений запит як фільтр приєднання реплікації злиття, тому я не можу просто додати в інший тип запиту на жаль.
ОНОВЛЕННЯ: Наприклад, це типи індексів, які я додаю,
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
столі?