Faire usage de l'index lors de la JOINTURE avec l'encontre de plusieurs colonnes

Simplifié, j'ai deux tables, contacts et donotcall

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
);

Je voudrais voir ce que les contacts correspond au numéro de téléphone dans une liste spécifique de DoNotCall téléphone.
Pour accélérer la recherche, j'ai indexé donotcall sur list_id et phone.

Quand je fais la JOINTURE suivante, il prend beaucoup de temps (par exemple. 9 secondes):

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)  

Faire usage de l'index lors de la JOINTURE avec l'encontre de plusieurs colonnes

Plan d'exécution sur Pastebin

Alors que si j'LEFT JOIN sur chaque champ téléphone séparément, il fonctionne beaucoup plus vite (par exemple. 1.5 secondes):

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

Faire usage de l'index lors de la JOINTURE avec l'encontre de plusieurs colonnes

Plan d'exécution sur Pastebin

Mon hypothèse est que le premier extrait s'exécute lentement, car il n'utilise pas l'index sur donotcall.
Alors, comment faire une jointure vers plusieurs colonnes et de toujours utiliser l'index?

Ce que vous devez faire est de fixer votre datbase structure. Vous ne devriez JAMAIS avoir phone1, fixe2, phone3, phone4 - qui indique que vous avez besoin d'une table d'enfant.
Point à noter. J'aurais également fait différemment si j'ai eu le choix. Mais parfois, vous êtes coincé avec une structure que d'autres ont créé, sans espoir de refactoring.

OriginalL'auteur ANisus | 2013-09-04