uproszczony, mam dwie tabele, contacts
i donotcall
Wykorzystaj indeksu kiedy JOIN'ing przeciwko wielu kolumn
CREATE TABLE contacts
(
id int PRIMARY KEY,
phone1 varchar(20) NULL,
phone2 varchar(20) NULL,
phone3 varchar(20) NULL,
phone4 varchar(20) NULL
);
CREATE TABLE donotcall
(
list_id int NOT NULL,
phone varchar(20) NOT NULL
);
CREATE NONCLUSTERED INDEX IX_donotcall_list_phone ON donotcall
(
list_id ASC,
phone ASC
);
chciałbym zobaczyć, co pasuje do kontaktów numer telefonu w specjalnym liście DoNotCall telefonu. Dla szybszego wyszukiwania, zaindeksowałem donotcall
na list_id
i phone
.
Kiedy dokonać następujących DOŁĄCZ to zajmuje dużo czasu (na przykład 9 sekund.):
SELECT DISTINCT c.id
FROM contacts c
JOIN donotcall d
ON d.list_id = 1
AND d.phone IN (c.phone1, c.phone2, c.phone3, c.phone4)
Chociaż gdybym LEFT JOIN na każdym polu telefonu osobno go działa znacznie szybciej (np. 1,5 sekundy):
SELECT c.id
FROM contacts c
LEFT JOIN donotcall d1
ON d1.list_id = 1
AND d1.phone = c.phone1
LEFT JOIN donotcall d2
ON d2.list_id = 1
AND d2.phone = c.phone2
LEFT JOIN donotcall d3
ON d3.list_id = 1
AND d3.phone = c.phone3
LEFT JOIN donotcall d4
ON d4.list_id = 1
AND d4.phone = c.phone4
WHERE
d1.phone IS NOT NULL
OR d2.phone IS NOT NULL
OR d3.phone IS NOT NULL
OR d4.phone IS NOT NULL
Moje założenie jest, że pierwszy fragment przebiega powoli, ponieważ nie wykorzystują indeks na donotcall
.
A więc, jak wykonać sprzężenie w kierunku wielu kolumn i nadal korzystać z indeksu?
Naprawdę musisz naprawić strukturę bazy danych. NIGDY nie powinieneś mieć telefonu1, telefonu2, telefonu3, telefonu4 - który wskazuje, że potrzebujesz dziecięcego stołu. – HLGEM
@HLGEM: Punkt oznaczony. Zrobiłbym to inaczej, gdybym miał wybór. Ale czasami utkniesz w strukturze, którą stworzyli inni, bez nadziei na refaktoryzację. – ANisus