简体   繁体   English

如何在SQL Server Compact Edition 4上修复此查询性能

[英]how to fix this query performance on SQL Server Compact Edition 4

i have the following SQL Query which runs on SQL Server CE 4 我有以下SQL查询在SQL Server CE 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]

this query takes a long time to execute but if i change the Part 此查询需要很长时间才能执行,但如果我更改了部件

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

To

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

So the full query becomes 所以完整的查询就变成了

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]

then the performance becomes very fast. 然后表现变得非常快。
the problem is that the part that was changed if taken by itself is pretty fast. 问题是如果自己采取的部分变化非常快。 but for some reason the execution plan of the first query shows that the "actual number of rows" in the index scan is 160,016 while the total number of rows in the table MovieFolder is 2,192. 但由于某种原因,第一个查询的执行计划显示索引扫描中的“实际行数”为160,016,而表MovieFolder中的总行数为2,192。 and the "Estimated number of rows" is 2,192. 而“估计行数”是2,192。
so i think the problem is in the number of rows but i cant figure out why its all messed up. 所以我认为问题在于行数,但我无法弄清楚为什么它全部搞砸了。
any help will be appreciated :) thanks 任何帮助将不胜感激:)谢谢

the schema of the tables is below 表格的架构如下

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

I think you're running into a correlated subquery problem. 我认为你遇到了一个相关的子查询问题。 The query part you're experimenting with is part of a JOIN condition, so it is fully evaluated for every potentially matching row. 您正在尝试的查询部分是JOIN条件的一部分,因此对每个可能匹配的行进行完全评估。 You're making your SQL engine do the second 'GROUP BY' for every row produced by the FROM clause. 您正在使您的SQL引擎为FROM子句生成的每一行执行第二个“GROUP BY”。 So it's reading 2192 rows to do the group by for each and every row produced by the FROM clause. 所以它正在读取2192行来为FROM子句生成的每一行执行group by。

This suggest you're getting 73 rows in the FROM clause grouping (2192 * 73 = 160 016) 这表明你在FROM子句分组中获得了73行(2192 * 73 = 160 016)

When you change it to do SELECT 1, you eliminate the table-scan read for grouping. 当您将其更改为执行SELECT 1时,将消除用于分组的表扫描读取。

DaveE is right about the issue with your correlated subquery. DaveE对你的相关子查询的问题是正确的。 When these issues arise you often need to rethink your entire query. 出现这些问题时,您经常需要重新考虑整个查询。 If anything else fails you can probably save time extracting your sub-query to a temporary table like this: 如果还有其他任何问题,您可以节省将子查询提取到临时表的时间,如下所示:

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

i think if found the problem. 我想如果发现了问题。
but i would like people to tell me if this indeed the problem. 但我希望有人告诉我这是否确实存在问题。
the problem is that the 2 sub queries create some kind of like temp table (dont know how to call it). 问题是2个子查询创建了某种类似临时表(不知道如何调用它)。
but these 2 temp table dont contain a clustered index on [FK_MovieID]. 但是这两个临时表在[FK_MovieID]上不包含聚簇索引。
so when the external join tries to join them it need to scan them several times and and this is mainly the problem. 因此,当外部联接尝试加入它们时,需要多次扫描它们,这主要是问题所在。
now if i can only fix this ? 现在,如果我只能解决这个问题?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM