Wir haben eine Ansicht, die für Einzelelementabfragen optimiert ist (200 ms keine Parallelität):
select *
from OptimizedForSingleObjectIdView e2i
where ObjectId = 3374700
Es funktioniert auch mit kleinen Mengen statischer IDs (~ 5).
select *
from OptimizedForSingleObjectIdView e2i
where ObjectId in (3374700, 3374710, 3374720, 3374730, 3374740);
Wenn die Objekte jedoch von einer externen Quelle stammen, wird ein langsamer Plan generiert. Der Ausführungsplan zeigt, dass der Ausführungszweig für den Ansichtsteil das Prädikat für ObjectId ignoriert, während er sie im ursprünglichen Fall zum Ausführen von Indexsuchen verwendet.
select v.*
from
(
select top 1 ObjectId from Objects
where ObjectId % 10 = 0
order by ObjectId
) o
join OptimizedForSingleObjectIdView v -- (also tried inner loop join)
on v.ObjectId = o.ObjectId;
Wir möchten nicht in "dual" investieren, um die Ansicht für nicht singuläre Fälle zu optimieren. Die Lösung, die wir "suchen", besteht vielmehr darin, die Ansicht wiederholt einmal pro Objekt aufzurufen, ohne auf einen SP zurückzugreifen .
Meistens ruft die folgende Lösung die Ansicht zeilenweise auf. Allerdings diesmal nicht und nicht einmal für nur 1 Objekt:
select v.*
from
(
select top 1 ObjectId
from Objects
where ObjectId % 10 = 0 -- non-trivial predicate
order by ObjectId
) o
cross apply
(
select top 2000000000 *
from OptimizedForSingleObjectIdView v_
where ObjectId = o.ObjectId
order by v_.SomeField
) v;
Zu einer Zeit dachte ich, es gäbe eine Behauptung, dass Cross Apply für die zeilenweise Ausführung garantiert sei, wenn eine UDF aufgerufen wird, aber dies schlug auch fehl:
create function FunctionCallingView(@pObjectId bigint)
returns table
as
return select *
from OptimizedForSingleObjectIdView
where ObjectId = @pObjectId;
select v.*
from
(
select top 1 ObjectId
from Objects
where ObjectId % 10 = 0
order by ObjectId
) o
cross apply FunctionCallingView(o.ObjectId) v
Das Hinzufügen einer Option (Reihenfolge erzwingen) hat nicht geholfen - es gibt jedoch bereits zwei Hash-Hinweise in der Ansicht. Das vorübergehende Entfernen half nicht und verlangsamte den Einzelfall.
Hier ist ein Ausschnitt des geschätzten Plans für den funktionsbasierten langsamen Fall. Die Schätzung von 1 Zeile ist korrekt. Weit rechts (nicht gezeigt) befindet sich ein Suchprädikat, das dieses Top-1-Ergebnis nicht enthält. Dies scheint anderen Fällen ähnlich zu sein, in denen einzelne untersuchte Werte aus Tabellensuchen nicht anderswo als Suchprädikate verwendet werden.
OPTION(FAST 1)
Hinweis verwenden?