2013-07-10 6 views
7

Ich habe eine SQL-Abfrage, die etwa 30 Sekunden dauert, um 1 Datensatz auszuführen. Die im CROSS APPLY verwendete Funktion ist sofort verfügbar, wenn sie mit der BrandId dieses Datensatzes ausgeführt wird.CROSS APPLY Leistungsunterschied

SELECT 
    b.BrandId, 
    b.Name, 
    ah.Type, 
    c.ContactEmails, 
    c.ContactNumbers, 
    c.ContactLinks 
FROM 
    @IdsToFilterBy ids 
JOIN dbo.AccountHandler ah ON ah.AccountHandlerId = ids.Id 
JOIN dbo.Brand b ON ah.RepresentedByBrandId = b.BrandId 
CROSS APPLY dbo.[fn_GetBrandContactDetails](b.BrandId) AS c 

Allerdings, wenn ich nur die Tabelle ändern ich die brandid aus für die CROSS APPLY ..

SELECT 
    b.BrandId, 
    b.Name, 
    ah.Type, 
    c.ContactEmails, 
    c.ContactNumbers, 
    c.ContactLinks 
FROM 
    @IdsToFilterBy ids 
JOIN dbo.AccountHandler ah ON ah.AccountHandlerId = ids.Id 
JOIN dbo.Brand b ON ah.RepresentedByBrandId = b.BrandId 
CROSS APPLY dbo.[fn_GetBrandContactDetails](ah.RepresentedByBrandId) AS c <-- change here 

die Abfrage jetzt dauert nur 2 Sekunden zu laufen. Wenn ich bei dbo.Brand b ON cah.RepresentedByBrandId = b.BrandId bin, würde ich erwarten, dass sie gleich sind.

Kann jemand erklären, warum der große Leistungsunterschied?

UPDATE

Der Unterschied ist, weil die CROSS APPLY auf die gesamte Marke Tabelle ausgeführt wird, wenn ich b.BrandId und die ganze AccountHandler Tabelle verwenden, wenn ich ah.RepresentedByBrandId verwenden. Die AccountHandler-Tabelle ist erheblich kleiner.

Allerdings habe ich erwartet, dass die CROSS APPLY nur auf die Ergebnisse der JOINs läuft, die eine 1 Rekord ist. Ist das möglich oder habe ich CROSS APPLY nicht verstanden?

+2

gibt der unterschiedliche Ausführungsplan keinen Hinweis? –

+0

Ich bin nicht gut darin, diese zu lesen, aber es scheint, es läuft das Kreuz für die gesamte Marken Tabelle anwenden, wenn ich b.BrandId und nicht nur die Teilmenge von der Join – Magpie

+0

Mögliche Ich bin blind. Aber wo wurde 'cah' Alias ​​in der zweiten Abfrage deklariert? – Devart

Antwort

14

Es gefunden.

Um zu erzwingen, wenden Sie das Kreuz auf dem Unter Satz von Ergebnissen laufen von der JOIN und nicht auf dem ganzen Tisch, bevor die JOINS I OPTION (FORCE ORDER) verwenden

SELECT 
    b.BrandId, 
    b.Name, 
    ah.Type, 
    c.ContactEmails, 
    c.ContactNumbers, 
    c.ContactLinks 
FROM 
    @IdsToFilterBy ids 
JOIN dbo.AccountHandler ah ON ah.AccountHandlerId = ids.Id 
JOIN dbo.Brand b ON ah.RepresentedByBrandId = b.BrandId 
CROSS APPLY dbo.[fn_GetBrandContactDetails](b.BrandId) AS c 
OPTION (FORCE ORDER) 

Dies läuft jetzt sofort und Blick auf der Ausführungsplan Die Funktion wird nur für das eine Ergebnis und nicht für die gesamte db-Tabelle aufgerufen.

+2

FORCE ORDER hilft nicht immer, ich musste eine Zwischentabelle verwenden, um die Ergebnisse der "Hauptabfrage" zu speichern, und sie dann mit der Funktion übernehmen. –

-1

Ich hatte das gleiche Problem und löste es mit OUTER APPLY anstelle von CROSS APPLY.