Mam strukturę bazy danych podobną do tej,
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
Celem tabeli DispatchLink jest połączenie ze sobą dwóch rekordów Dispatch. Nawiasem mówiąc, używam złożonego klucza głównego na mojej tabeli wysyłki z powodu starszej wersji, więc nie mogę tego zmienić bez większego bólu. Również tabela linków może być niewłaściwa? Ale znowu dziedzictwo.
Więc moje pytanie, jeśli uruchomię to zapytanie
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
Nigdy nie mogę zmusić go do wyszukiwania indeksu w tabeli DispatchLink. Zawsze wykonuje pełne skanowanie indeksu. To jest w porządku z kilkoma rekordami, ale gdy masz 50000 w tej tabeli, skanuje 50000 rekordów w indeksie zgodnie z planem zapytań. Wynika to z faktu, że w klauzuli łączenia występują „ands” i „ors”, ale nie mogę się zastanowić, dlaczego SQL nie może zamiast tego wykonać kilku wyszukiwań indeksu, po jednej dla lewej strony „lub”, i jeden po prawej stronie „lub”.
Chciałbym wyjaśnienia tego, a nie sugestii, aby przyspieszyć zapytanie, chyba że można to zrobić bez dostosowania zapytania. Powodem jest to, że używam powyższego zapytania jako filtru łączenia replikacji scalającej, więc nie mogę po prostu dodać innego typu zapytania.
AKTUALIZACJA: Na przykład są to typy indeksów, które dodawałem,
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)
Używa więc indeksów, ale skanuje indeks w całym indeksie, więc 50000 rekordów skanuje 50000 rekordów w indeksie.
DispatchLink
stole?