运行此查询的框是在数据中心中运行的专用服务器.
AMD Opteron 1354四核2.20GHz 2GB内存Windows Server 2008 x64(是的,我知道我只有2GB内存,当项目上线时我升级到8GB).
因此,我在表格中创建了250,000个虚拟行,以真正压力测试LINQ to SQL生成的一些查询,并确保它们不会太糟糕,我注意到其中一个正在花费大量时间.
我使用索引将此查询缩短到17秒,但为了这个答案,我从头到尾删除了它们.只有索引是主键.
Stories table -- [ID] [int] IDENTITY(1,1) NOT NULL, [UserID] [int] NOT NULL, [CategoryID] [int] NOT NULL, [VoteCount] [int] NOT NULL, [CommentCount] [int] NOT NULL, [Title] [nvarchar](96) NOT NULL, [Description] [nvarchar](1024) NOT NULL, [CreatedAt] [datetime] NOT NULL, [UniqueName] [nvarchar](96) NOT NULL, [Url] [nvarchar](512) NOT NULL, [LastActivityAt] [datetime] NOT NULL, Categories table -- [ID] [int] IDENTITY(1,1) NOT NULL, [ShortName] [nvarchar](8) NOT NULL, [Name] [nvarchar](64) NOT NULL, Users table -- [ID] [int] IDENTITY(1,1) NOT NULL, [Username] [nvarchar](32) NOT NULL, [Password] [nvarchar](64) NOT NULL, [Email] [nvarchar](320) NOT NULL, [CreatedAt] [datetime] NOT NULL, [LastActivityAt] [datetime] NOT NULL,
目前在数据库中有1个用户,1个类别和250,000个故事,我试图运行此查询.
SELECT TOP(10) * FROM Stories INNER JOIN Categories ON Categories.ID = Stories.CategoryID INNER JOIN Users ON Users.ID = Stories.UserID ORDER BY Stories.LastActivityAt
查询需要52秒才能运行,CPU使用率徘徊在2-3%,Membery是1.1GB,900MB可用,但磁盘使用率似乎失控.它是@ 100MB /秒,其中2/3是写入tempdb.mdf,其余的是从tempdb.mdf读取.
现在有趣的部分......
SELECT TOP(10) * FROM Stories INNER JOIN Categories ON Categories.ID = Stories.CategoryID INNER JOIN Users ON Users.ID = Stories.UserID SELECT TOP(10) * FROM Stories INNER JOIN Users ON Users.ID = Stories.UserID ORDER BY Stories.LastActivityAt SELECT TOP(10) * FROM Stories INNER JOIN Categories ON Categories.ID = Stories.CategoryID ORDER BY Stories.LastActivityAt
所有这三个查询都是即时的.
Exec计划第一次查询.
http://i43.tinypic.com/xp6gi1.png
Exec计划其他3个查询(按顺序).
http://i43.tinypic.com/30124bp.png
http://i44.tinypic.com/13yjml1.png
http://i43.tinypic.com/33uejf.png
任何帮助将非常感激.
添加索引后执行计划(再次降至17秒).
http://i39.tinypic.com/2008ytx.png
我从每个人那里得到了很多有用的反馈,我感谢你,我在这里尝试了一个新的角度.我查询我需要的故事,然后在单独的查询中获取类别和用户以及3个查询它只需要250毫秒......我不明白这个问题但是如果它有效并且在250毫秒时暂时不会少于我坚持下去.这是我用来测试它的代码.
DBDataContext db = new DBDataContext(); Console.ReadLine(); Stopwatch sw = Stopwatch.StartNew(); var stories = db.Stories.OrderBy(s => s.LastActivityAt).Take(10).ToList(); var storyIDs = stories.Select(c => c.ID); var categories = db.Categories.Where(c => storyIDs.Contains(c.ID)).ToList(); var users = db.Users.Where(u => storyIDs.Contains(u.ID)).ToList(); sw.Stop(); Console.WriteLine(sw.ElapsedMilliseconds);
cdonner.. 13
尝试在Stories.LastActivityAt上添加索引.我认为执行计划中的聚簇索引扫描可能是由于排序造成的.
编辑:由于我的查询在瞬间返回,行只有几个字节长,但已经运行了5分钟,并且在我添加了2K varchar之后仍在继续,我认为Mitch有一个观点.它是无关紧要的数据量,但这可以在查询中修复.
尝试将join,sort和top(10)放在视图或嵌套查询中,然后再与故事表联接以获取所需的10行的其余数据.
像这样:
select * from ( SELECT TOP(10) id, categoryID, userID FROM Stories ORDER BY Stories.LastActivityAt ) s INNER JOIN Stories ON Stories.ID = s.id INNER JOIN Categories ON Categories.ID = s.CategoryID INNER JOIN Users ON Users.ID = s.UserID
如果你有LastActivityAt的索引,这应该运行得非常快.
尝试在Stories.LastActivityAt上添加索引.我认为执行计划中的聚簇索引扫描可能是由于排序造成的.
编辑:由于我的查询在瞬间返回,行只有几个字节长,但已经运行了5分钟,并且在我添加了2K varchar之后仍在继续,我认为Mitch有一个观点.它是无关紧要的数据量,但这可以在查询中修复.
尝试将join,sort和top(10)放在视图或嵌套查询中,然后再与故事表联接以获取所需的10行的其余数据.
像这样:
select * from ( SELECT TOP(10) id, categoryID, userID FROM Stories ORDER BY Stories.LastActivityAt ) s INNER JOIN Stories ON Stories.ID = s.id INNER JOIN Categories ON Categories.ID = s.CategoryID INNER JOIN Users ON Users.ID = s.UserID
如果你有LastActivityAt的索引,这应该运行得非常快.