2017-02-08 1 views
2

Ich habe die folgende Abfrage, ist seine Laufzeit ~ 2 Sekunden, bis ich beitreten ProductStores auf StoreID, die es auf ~ 3 Minuten erhöht, Beitritt nur auf ProductID hält es bei ~ 2 Sekunden.Langsam Join am Composite Primärschlüssel

SELECT 
    Enabled = pp.PspEnabled 
    , StockStatusID = ss.ID 
    , WebSellable = pp.PspWebSellable 
    , CSSellable = pp.PspCsSellable 
FROM 
    #ExternalProducts pp 
JOIN 
    Product p ON p.ExternalCode = pp.code 
JOIN 
    Stores s ON s.Name = pp.p_externalStore 
JOIN 
    StockStatus ss ON ss.Name = pp.PspStockStatus 
JOIN 
    ProductStores ps ON (/* Store join increases time only */ ps.StoreID = s.ID AND ps.ProductID = p.ID) 

Reihen:

  • Shops: 108
  • Produkt: 136'598
  • ProductStores: 609'963

Keys:

CONSTRAINT [PK_dbo.Stores] 
    PRIMARY KEY CLUSTERED ([ID] ASC) 
CONSTRAINT [PK_dbo.Product] 
    PRIMARY KEY CLUSTERED ([ID] ASC) 
CONSTRAINT [PK_dbo.ProductStores] 
    PRIMARY KEY CLUSTERED ([ProductID] ASC, [StoreID] ASC) 

CONSTRAINT [FK_dbo.ProductStores_dbo.Stores_SiteID] 
    FOREIGN KEY([StoreID]) REFERENCES [dbo].[Stores] ([ID]) 
CONSTRAINT [FK_dbo.ProductStores_dbo.Product_ProductID] 
    FOREIGN KEY([ProductID]) REFERENCES [dbo].[Product] ([ID]) 

Ausführungsplan:

Der Ausführungsplan zeigt die Masse Kosten aus einem Hash kommenden Match (Inner Join) mit einer Raute-Taste Probe [dbo].[Stores].Name und Raute-Taste Erstellen [#ExternalProducts].p_externalstore, die ich nehme an das Problem ist, aber ich bin ich mir nicht sicher, wie ich das interpretieren soll?

execution plan 1

execution plan 2

hash join

Jede Hilfe ist sehr zu schätzen!

+1

Ich glaube nicht, dass Sie tatsächlich den Index auf 'ProductStores' haben. –

+0

Doing ein 'SELECT * FROM sys.indexes ...' zeigt mir, es hat 'PX_dbo.ProductStores CLUSTERED',' IX_ProductID NONCLUSTERED', 'IX_StoreID NONCLUSTERED'. –

+0

Können Sie den Ausführungsplan posten? Haben Sie diese Abfrage auch im Tuning-Berater ausgeführt? Was ist in der Tempentabelle? –

Antwort

0

Denis Rubashkin bemerkte, dass die geschätzten und tatsächlichen Zeilennummern tatsächlich sehr unterschiedlich sind. Nachdem der UPDATE STATISTICS den Ausführungsplan nicht ändern konnte, reorganisierte ich die Abfrage, um von ProductStores zu ziehen und stattdessen von #ExternalProducts zu filtern, was es mir erlaubte, eine Nested Loop Join zu erzwingen (was ich bei kleineren Resultsets für wünschenswert hielt).

SELECT 
    Enabled = pp.PspEnabled 
    , StockStatusID = ss.ID 
    , WebSellable = pp.PspWebSellable 
    , CSSellable = pp.PspCsSellable 
FROM ProductStores ps 
JOIN Product p ON p.ID = ps.ProductID 
JOIN Stores s ON s.ID = ps.StoreID 
INNER LOOP JOIN #ExternalProducts pp ON (p.Code = pp.Code AND s.Name = pp.p_externalstore) 
JOIN StockStatus ss ON ss.Name = pp.PspStockStatus 

Dies reduziert die Abfragezeit auf ~ 7 Sekunden von ~ 3 Minuten, was für diesen Zweck akzeptabel ist!

Verwandte Themen