2011-10-29 49 views
3

我有它運行的SQL Server CE下面的SQL查詢4如何解決SQL Server上的這個查詢性能精簡版4

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] 

此查詢需要很長的時間來執行,但如果我改變部分

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

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

所以,完整的查詢變得

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] 

然後表現變得非常快。
問題是,如果自己拿的部分是相當快的變化。但出於某種原因,第一個查詢的執行計劃顯示索引掃描中的「實際行數」爲160,016,而表格MovieFolder中的總行數爲2,192。 和「估計的行數」是2,192。
所以我認爲問題是在行數,但我無法弄清楚爲什麼它的一切搞砸了。
任何幫助將不勝感激:) 感謝

表的模式如下

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 
+0

查詢的目的是什麼?爲什麼你需要內部加入每部電影的計數列表,當你不使用計數的任何東西? – Alex

+0

這是一個更大的查詢的一部分,但我孤立的部分,使放緩,並把它放在這裏,所以它可能讓其他人unerstand它:) – Karim

+0

你可以改變SELECT爲「SELECT [Join_ReleaseMinDatePost]。[FK_MovieID],[ReleaseMinDatePost],[FOLDERCOUNT]」所以它更有意義:) – Karim

回答

1

我認爲你正在運行到correlated subquery問題。您正在試驗的查詢部分是JOIN條件的一部分,因此每個可能匹配行都會對其進行全面評估。你正在讓你的SQL引擎爲FROM子句產生的每一行做第二個'GROUP BY'。因此,它讀取2192行,爲FROM子句生成的每一行執行group by。

此建議你在FROM子句中的分組(2192 * 73 = 160 016)

當你改變它做選擇1得到73行,你消除表掃描讀出的分組。

+0

感謝澄清,但如何這個問題能解決嗎?還有我覺得這個問題只有在SQL Server精簡版存在,而不是HTE大單(不確保雖然) – Karim

+0

也我不明白爲什麼「選擇1,[FK_MovieID] FROM [MovieFolder]」消除表掃描?,它應該從表我覺得FK_MovieID。 – Karim

+0

我已閱讀有關correltaed子查詢,我不覺得這個查詢是相關的,因爲他們不包括anyreference在主查詢的任何項目,也是我已閱讀,SQL Server精簡版不支持相關子查詢 – Karim

0

DaveE是正確的與您的相關子查詢的問題。當出現這些問題時,您經常需要重新考慮您的整個查詢。如果有什麼事情都失敗了,你大概可以節省時間,這樣您的提取子查詢到一個臨時表:

/* 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] 
+0

據我所知,在sql server精簡版中沒有臨時表。 – Karim

+0

呃......錯過了CE部分。不,那當然不適合你。抱歉。我建議你考慮一下,如果可以再... – Alex

+0

以及感謝反正沒有創建子查詢查詢:) – Karim

0

我認爲,如果發現了問題。
但我想人們告訴我,如果這確實是這個問題。
問題是,2個子查詢創建某種類似臨時表(不知道如何調用它)。
但這2個臨時表不包含[FK_MovieID]上的聚集索引。
所以當外部連接嘗試連接它們時,需要多次掃描它們,這主要是問題所在。
現在,如果我只能解決這個問題?