3 Stimmen

wie man diese Abfrageleistung auf SQL Server Compact Edition 4 beheben kann

Ich habe die folgende SQL-Abfrage, die auf SQL Server CE 4 läuft

SELECT [Join_ReleaseMinDatePost].[FK_MovieID]
  FROM ( 
          SELECT [FK_MovieID], MIN([DatePost]) AS [ReleaseMinDatePost] 
          FROM [Release] 
          GROUP BY [FK_MovieID] 
        ) [Join_ReleaseMinDatePost]
  INNER JOIN  
        ( 
          SELECT COUNT([ID]) AS [FolderCount], [FK_MovieID] 
          FROM [MovieFolder] 
          GROUP BY [FK_MovieID] 
        )  [Join_MovieFolder]
    ON [Join_MovieFolder].[FK_MovieID] = [Join_ReleaseMinDatePost].[FK_MovieID]

Diese Abfrage benötigt viel Zeit für die Ausführung, aber wenn ich den Teil

SELECT COUNT([ID]) AS [FolderCount], [FK_MovieID] FROM [MovieFolder] GROUP BY [FK_MovieID]

An

SELECT 1 AS [FolderCount], [FK_MovieID] FROM [MovieFolder]

Die vollständige Abfrage lautet also

SELECT [Join_ReleaseMinDatePost].[FK_MovieID]
FROM ( SELECT [FK_MovieID], MIN([DatePost]) AS [ReleaseMinDatePost] FROM [Release] GROUP BY [FK_MovieID] ) [Join_ReleaseMinDatePost]
INNER  JOIN  (SELECT 1 AS [FolderCount], [FK_MovieID] FROM [MovieFolder] ) [Join_MovieFolder]
ON [Join_MovieFolder].[FK_MovieID] = [Join_ReleaseMinDatePost].[FK_MovieID]

dann wird die Leistung sehr schnell.
Das Problem ist, dass der Teil, der geändert wurde, wenn durch selbst genommen ist ziemlich schnell. aber aus irgendeinem Grund der Ausführungsplan der ersten Abfrage zeigt, dass die "tatsächliche Anzahl von Zeilen" in den Index-Scan 160.016 ist, während die Gesamtzahl der Zeilen in der Tabelle MovieFolder 2.192 ist. und die "geschätzte Anzahl der Zeilen" 2.192 beträgt.
Ich denke also, das Problem liegt in der Anzahl der Zeilen, aber ich kann nicht herausfinden, warum alles durcheinander ist.
jede Hilfe wird geschätzt :) danke

das Schema der Tabellen lautet wie folgt

CREATE TABLE [Release] (
  [ID] int NOT NULL
, [FD_ForumID] int NOT NULL
, [FK_MovieID] int NULL
, [DatePost] datetime NULL
);
GO
ALTER TABLE [Release] ADD CONSTRAINT [PK__Release__0000000000000052] PRIMARY KEY ([ID]);
GO
CREATE INDEX [IX_Release_DatePost] ON [Release] ([DatePost] ASC);
GO
CREATE INDEX [IX_Release_FD_ForumID] ON [Release] ([FD_ForumID] ASC);
GO
CREATE INDEX [IX_Release_FK_MovieID] ON [Release] ([FK_MovieID] ASC);
GO
CREATE UNIQUE INDEX [UQ__Release__0000000000000057] ON [Release] ([ID] ASC);
GO

CREATE TABLE [MovieFolder] (
  [ID] int NOT NULL  IDENTITY (1,1)
, [Path] nvarchar(500) NOT NULL
, [FK_MovieID] int NULL
, [Seen] bit NULL
);
GO
ALTER TABLE [MovieFolder] ADD CONSTRAINT [PK_MovieFolder] PRIMARY KEY ([ID]);
GO
CREATE INDEX [IX_MovieFolder_FK_MovieID] ON [MovieFolder] ([FK_MovieID] ASC);
GO
CREATE INDEX [IX_MovieFolder_Seen] ON [MovieFolder] ([Seen] ASC);
GO
CREATE UNIQUE INDEX [UQ__MovieFolder__0000000000000019] ON [MovieFolder] ([ID] ASC);
GO
CREATE UNIQUE INDEX [UQ__MovieFolder__0000000000000020] ON [MovieFolder] ([Path] ASC);
GO

1voto

DaveE Punkte 3559

Ich glaube, Sie haben ein Problem mit der korrelierte Unterabfrage Problem. Der Teil der Abfrage, mit dem Sie experimentieren, ist Teil einer JOIN-Bedingung, so dass er für jede Abfrage vollständig ausgewertet wird. potenziell passend Zeile. Sie veranlassen Ihre SQL-Engine, die zweite "GROUP BY"-Anweisung für jede durch die FROM-Klausel erzeugte Zeile auszuführen. Es werden also 2192 Zeilen gelesen, um die Gruppierung nach jeder einzelnen Zeile der FROM-Klausel durchzuführen.

Dies lässt vermuten, dass Sie 73 Zeilen in der Gruppierung der FROM-Klausel erhalten (2192 * 73 = 160 016)

Wenn Sie SELECT 1 verwenden, entfällt das Lesen der Tabelle für die Gruppierung.

0voto

Alex Punkte 1973

DaveE hat Recht, was das Problem mit Ihrer korrelierten Unterabfrage betrifft. Wenn diese Probleme auftreten, müssen Sie oft Ihre gesamte Abfrage überdenken. Wenn alles andere fehlschlägt, können Sie wahrscheinlich Zeit sparen, indem Sie Ihre Unterabfrage in eine temporäre Tabelle wie diese extrahieren:

/* Declare in-memory temp table */
DECLARE @Join_MovieFolder TABLE ( 
     count INT,
     movieId INT )

 /* Insert data into temp table */
 INSERT INTO @Join_MovieFolder ( count, movieId ) 
 SELECT COUNT([ID]) AS [FolderCount], [FK_MovieID] 
          FROM [MovieFolder] 
          GROUP BY [FK_MovieID] 

 /* Inner join the temp table to avoid excessive sub-quering */
SELECT [Join_ReleaseMinDatePost].[FK_MovieID]
  FROM ( 
          SELECT [FK_MovieID], MIN([DatePost]) AS [ReleaseMinDatePost] 
          FROM [Release] 
          GROUP BY [FK_MovieID] 
        ) [Join_ReleaseMinDatePost]
  INNER JOIN @Join_MovieFolder 
    ON @Join_MovieFolder.movieId = [Join_ReleaseMinDatePost].[FK_MovieID]

0voto

Karim Punkte 5917

Ich glaube, ich habe das Problem gefunden.
aber ich möchte, dass man mir sagt, ob dies tatsächlich das Problem ist.
das Problem ist, dass die 2 Unterabfragen eine Art von wie temporäre Tabelle erstellen (weiß nicht, wie man es nennen).
aber diese 2 temporären Tabellen enthalten keinen geclusterten Index auf [FK_MovieID].
Wenn also die externe Verknüpfung versucht, sie zu verknüpfen, müssen sie mehrmals gescannt werden, und das ist hauptsächlich das Problem.
Wenn ich das jetzt nur in Ordnung bringen könnte?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X