我正在创建一个包含Posts
和Comments
的网页。但是,在呈现Comments
期间检索每个Post
的{{1}}时,检索速度非常慢。我的猜测是,这是由于频繁打开/关闭连接。无论如何,它都不能很好地扩展。
要解决此问题,我正在考虑将两个实体合并为一个,并以多边形方式对Post
和Posts
进行建模。换句话说,Comments
成为超类,由Entry
和Post
分类。
有人可以就这是否是一种有效的方法给我一些建议吗?或者,我愿意接受其他建议,这些建议也可能解决我可能没有想到的嵌套Comment
/ Repeater
性能问题。
答案 0 :(得分:1)
即使您的博客上有数千条评论的博客,它仍然可以正常运作 RDBMS表经常会遇到数百万条记录。
频繁打开和关闭连接将成为性能瓶颈 您应该一次获取所有数据,然后将其传递给嵌套的转发器。
答案 1 :(得分:1)
扩展nunespascal说的话:
无论您是通过两个单独的表将数据作为两个单独的实体拉回来还是将它从多个表中拉回到同一个表中,听起来您遇到的问题是如何您正在请求数据。
在C#中考虑这两种方法-ish EF伪代码:
方法1:迭代加载儿童
var posts = db.Posts;
foreach (Post p in posts) {
Html.Render(p);
var comments = db.Comments.Where(c => c.PostId == p.PostId);
foreach (Comment c in comments) {
Html.Render(c);
}
}
这听起来就像你在当前的转发迭代中所做的那样。对于您来的每个帖子,加载属于它的评论 - 并将其渲染出来。
这确实创建了您所描述的瓶颈,您在其中打开/关闭大量连接并运行许多单独的原子SQL语句。如果可以,请避免这种情况。
方法2:一起加载父母/孩子
var posts = db.Posts.Top(10);
// ^ The .Top(10) limits the result-set to a manageable number of posts (10).
var ids = posts.Select(p => p.PostId);
// ^ This line creates an Enumerable list of the IDs of your loaded posts.
var comments = db.Comments.Where(c => ids.Contains(c.PostId));
// ^ This line loads all the comments which belong to the 10 posts you loaded.
foreach (Post p in posts) {
Html.Render(p);
foreach (Comment c in comments.Where(c => c.PostId == p.PostId)) {
// This loop iterates the comments in the same way the previous example
// showed, with the exception that it iterates *in memory*, rather than
// running additional SQL on each iteration.
Html.Render(c);
}
}
因为你在第二个例子中加载了内存中的所有项目,所以你保存了所有的往返行程 - 只生成了2个SQL语句,这两个语句都是在开始时运行的。
如果您实际使用的是EF4 / 5(以上代码所基于的),您实际上甚至可以执行以下操作:
var posts = db.Posts.Include("Comments");
// ^ This line loads both Posts and Comments in a single SQL statement
foreach (Post p in posts) {
Html.Render(p);
foreach (Comment c in p.Comments) {
// EF5 and other ORMs can create a .Comments property which contains an
// Enumerable list of the comments, already filtered on the FK binding
Html.Render(c);
}
}