In SQL Server 2012 habe ich eine Tabellenwertfunktion mit Verknüpfung zu einer anderen Tabelle. Ich muss die Anzahl der Zeilen für diese 'Tabellenwertfunktion' zählen. Wenn ich den Ausführungsplan überprüfe, sehe ich die linke Verknüpfungstabelle. Warum? Wie kann die linksverknüpfte Tabelle die Anzahl der zurückgegebenen Zeilen beeinflussen? Ich würde erwarten, dass die DB-Engine die linke gemeinsame Tabelle in der SELECT count (..) Abfrage nicht auswerten muss.
Select count(realtyId) FROM [dbo].[GetFilteredRealtyFulltext]('"praha"')
Der Ausführungsplan:
Die Tabellenwertfunktion:
CREATE FUNCTION [dbo].[GetFilteredRealtyFulltext]
(@criteria nvarchar(4000))
RETURNS TABLE
AS
RETURN (SELECT
realty.Id AS realtyId,
realty.OwnerId,
realty.Caption AS realtyCaption,
realty.BusinessCategory,
realty.Created,
realty.LastChanged,
realty.LastChangedType,
realty.Price,
realty.Pricing,
realty.PriceCurrency,
realty.PriceNote,
realty.PricePlus,
realty.OfferState,
realty.OrderCode,
realty.PublishAddress,
realty.PublishMap,
realty.AreaLand,
realty.AreaCover,
realty.AreaFloor,
realty.Views,
realty.TopPoints,
realty.Radius,
COALESCE(realty.Wgs84X, ruian_cobce.Wgs84X, ruian_obec.Wgs84X) as Wgs84X,
COALESCE(realty.Wgs84Y, ruian_cobce.Wgs84Y, ruian_obec.Wgs84Y) as Wgs84Y,
realty.krajId,
realty.okresId,
realty.obecId,
realty.cobceId,
IsNull(CONVERT(int,realty.Ranking),0) as Ranking,
realty.energy_efficiency_rating,
realty.energy_performance_attachment,
realty.energy_performance_certificate,
realty.energy_performance_summary,
Category.Id AS CategoryId,
Category.ParentCategoryId,
Category.WholeName,
okres.nazev AS okres,
ruian_obec.nazev AS obec,
ruian_cobce.nazev AS cobce,
ExternFile.ServerPath,
Person.ParentPersonId,
( COALESCE(ftR.Rank,0) + COALESCE(ftObec.Rank,0) + COALESCE(ftOkres.Rank,0) + COALESCE(ftpobvod.Rank,0)) AS FtRank
FROM realty
JOIN Category ON realty.CategoryId = Category.Id
LEFT JOIN ruian_cobce ON realty.cobceId = ruian_cobce.cobce_kod
LEFT JOIN ruian_obec ON realty.obecId = ruian_obec.obec_kod
LEFT JOIN okres ON realty.okresId = okres.okres_kod
LEFT JOIN ExternFile ON realty.Id = ExternFile.ForeignId AND ExternFile.IsMain = 1 AND ExternFile.ForeignTable = 5
INNER JOIN Person ON realty.OwnerId = Person.Id
Left JOIN CONTAINSTABLE(Realty, *, @criteria) ftR ON realty.Id = ftR.[Key]
Left JOIN CONTAINSTABLE(ruian_obec, *, @criteria) ftObec ON realty.obecId = ftObec.[Key]
Left JOIN CONTAINSTABLE(Okres, *, @criteria) ftOkres ON realty.okresId = ftOkres.[Key]
Left JOIN CONTAINSTABLE(pobvod, *, @criteria) ftpobvod ON realty.pobvodId = ftpobvod.[Key]
WHERE Person.ConfirmStatus = 1
AND ( COALESCE(ftR.Rank,0) + COALESCE(ftObec.Rank,0) + COALESCE(ftOkres.Rank,0) + COALESCE(ftpobvod.Rank,0)) > 0
)
AKTUALISIEREN:
Ich füge einen einzigartigen Index hinzu, um der Idee von Rob Farley zu folgen:
Create unique nonclustered index ExternFileIsMainUnique ON ExternFile(ForeignId) WHERE IsMain = 1 AND ForeignTable = 5
Und indiziert von DB Engine vorgeschlagen:
CREATE NONCLUSTERED INDEX [RealtyOwnerLocation] ON [dbo].[Realty]
([OwnerId] ASC) INCLUDE ([Id], [okresId], [obecId], [pobvodId]) GO
Der Einfachheit halber entferne ich die Bedingung
WHERE Person.ConfirmStatus = 1
von der oben angegebenen Wertfunktion.
Jetzt ist der Ausführungsplan viel einfacher, berührt aber immer noch die Tabelle ExternFile:
Vielleicht ist SQL Server nicht klug genug?
quelle