2017-03-15 2 views
5

Angenommen, ich habe eine Liste der Zeichenfolge, die vom Client gesendet wird, in diesem Fall Regionen. Und ich habe eine Tabelle namens Compliance-Regionen. Ich möchte nach den Zeilen suchen, für die eine name-Eigenschaft und ein region-Objekt in der Zeile vorhanden sein müssen.SQL INNER JOIN vs Wo gibt es Leistungsbewertung

In der LINQ kann ich es auf zwei verschiedene Arten tun. Wie unten, und sie produzieren zwei verschiedene SQL-Abfragen. Meine Frage ist, welche sollte ich wählen? Welche Abfrage hat die bessere Leistung?

List<string> regions = new List<string>() { "Canada", "EN 50530" }; 

      var cregions = from c in complianceRegions 
          from r in regions 
          where c.Name.Equals(r) 
          select c; 

      var cregions2 = from c in complianceRegions 
          where regions.Any(x => x == c.Name) 
          select c; 

Die erzeugte sql ist unten gezeigt.

 -- cregions 
    SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Description] AS [Description] 
    FROM [Administration].[ComplianceRegions] AS [Extent1] 
    INNER JOIN (SELECT 
     N'Canada' AS [C1] 
     FROM (SELECT 1 AS X) AS [SingleRowTable1] 
    UNION ALL 
     SELECT 
     N'EN 50530' AS [C1] 
     FROM (SELECT 1 AS X) AS [SingleRowTable2]) AS [UnionAll1] ON [Extent1].[Name] = [UnionAll1].[C1] 

cregions

Und

--cregions2 
    SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Description] AS [Description] 
    FROM [Administration].[ComplianceRegions] AS [Extent1] 
    WHERE EXISTS (SELECT 
     1 AS [C1] 
     FROM (SELECT 
      N'Canada' AS [C1] 
      FROM (SELECT 1 AS X) AS [SingleRowTable1] 
     UNION ALL 
      SELECT 
      N'EN 50530' AS [C1] 
      FROM (SELECT 1 AS X) AS [SingleRowTable2]) AS [UnionAll1] 
     WHERE [UnionAll1].[C1] = [Extent1].[Name] 
    ) 

cregions2 Added Ausführungsplan wie gewünscht.

+2

* Welche Abfrage hat die bessere Leistung? * Was haben Ihre eigenen Tests ergeben? –

+0

der interessante Teil ist, wenn ich die gleiche Abfrage mehrmals ausführen, zwischenspeichert SQL Server die Abfrage und geben Sie mir falsche Leistung. –

+0

Warum verwendet die erste Abfrage 'Enthält' und die zweite' == '? Welcher ist der vorgesehene Vergleichsoperator? Momentan vergleichen Sie Äpfel mit Orangen. –

Antwort

2

Gegeben die zwei Alternativen, die zweite ist wahrscheinlich besser, weil es keinen Funktionsaufruf auf dem Spaltennamen gibt.

Allerdings sind die beiden nicht das Gleiche. Die erste macht eine teilweise Übereinstimmung und die zweite eine exakte Übereinstimmung. Du solltest wirklich denjenigen tun, der das tut, was du vorhast. Leistung ist sekundär zur Genauigkeit.

Beide sind schmerzhaft anzuschauen. Die Ausgabe von CHARINDEX() in einen Index umwandeln? Können wir "redundant" sagen?

Sie bitte die Frage, warum die Abfrage nicht einfach ist:

select . . . 
from [Administration].[ComplianceRegions] AS [Extent1] 
where Extent1.Name in (N'Canada', N'EN 50530'); 

Dies ist die einfachste und leistungsstärksten Version dieser Logik.

+0

, aber diese Abfragen werden automatisch generiert. Ich muss die bessere LINQ-Abfrage auswählen. –

+0

@FoyzulKarim: Sie müssen Ausführungspläne von beiden Abfragen und Schema, Anzahl der beteiligten Tabellen einfügen. Mit dieser Frage kann diese Frage nicht beantwortet werden – TheGameiswar

+0

* Warum die Abfrage nicht einfach ist ... * weil es sucht für teilweise Übereinstimmung? –

0

Zitate von @JNK Antwort in this post.

EXISTS verwendet, um einen Booleschen Wert zurück, JOIN kehrt eine ganz andere Tabelle

besteht nur, wenn eine Unterabfrage gibt Ergebnisse zu testen, verwendet wird, und Kurzschlüsse, sobald es tut. JOIN wird verwendet, um eine Ergebnismenge zu erweitern, indem sie mit zusätzlichen Feldern aus einer anderen Tabelle kombiniert wird, zu der eine Beziehung besteht.

In Ihrem Beispiel sind die Abfragen symbolisch äquivalent.

Im allgemeinen Gebrauch liegt vor, wenn:

Sie müssen keine Daten aus der verknüpften Tabelle zurückzukehren Sie haben Betrogenen in der verknüpften Tabelle (JOIN können doppelte Zeilen verursachen, wenn Werte wiederholt werden) Sie wollen check existence (benutze statt LEFT OUTER JOIN ... NULL-Bedingung) Wenn du richtige Indizes hast, werden die EXISTS meist genauso funktionieren wie der JOIN. Die Ausnahme liegt bei sehr komplizierten Unterabfragen, wo EXISTS normalerweise schneller verwendet werden kann.

Wenn Ihre JOIN-Taste nicht indexiert ist, kann EXISTS möglicherweise schneller verwendet werden, Sie müssen jedoch auf Ihre spezifischen Umstände testen.

JOIN-Syntax ist normalerweise einfacher zu lesen und klarer.

0

Diese Abfragen sind gleich. Und beide sind schrecklich, ich würde keinen von ihnen wählen. Sie haben fest codierte Werte, so dass sie nicht wiederverwendet werden können. Ich bin mir nicht sicher, ob die Autoparametrisierung von sql server damit umgehen kann, so dass der Ausführungsplancache wahrscheinlich leiden würde. Die richtige Lösung ist die Verwendung von Tabellenwerten, die leider bei Linq-Providern nicht unterstützt werden, soweit ich weiß. Also müssten Sie die Abfrage selbst machen, Sie können nur linq verwenden, um das Ergebnis zu materialisieren.

Sie können versuchen, die von Ivan Stoev zur Verfügung gestellte Lösung, wie gut es ist, hängt davon ab, was Ihr Anbieter produziert. Linq2sql skaliert nicht gut für längere Listen, da es so viele Parameter wie viele Elemente in der Liste, die Sie haben, erzeugt. Zumindest kann der Ausführungsplan wiederverwendet werden, wenn die Anzahl der Elemente in der Liste gleich ist.