2

我开始从事一个与 SO 非常相似的项目。我为我的应用程序创建了一个数据库(Code First EF-5 Sql server 2012),其中有很多表,包括Questions ans Answers。这两个表之间存在一对多的关系(一个问题可以有多个答案)。现在我也想在问题列表视图中显示每个问题的答案计数。

显而易见的方法是(如果 Answers 和 Questions 有一对多的关系,所以每个问题实体都有一个 List of Answers 对象)所以我们可以写一个简单的语句:

   question.Answers.Count;

但是我对这个查询有性能疑问。首先我告诉我我是如何决定这样做的(我对数据库没有太多经验,所以如果我走错了路,请纠正我

我在问题表名称中创建了一个额外的列,AnswerCount每次用户插入或删除问题的答案时都会更新该列。为此,我编写了一个 sql 触发器,在 Answer 表上的插入或删除事件上执行。这是触发器:

Create TRIGGER [dbo].[trg_Answer_INSERT_Delete]
ON [dbo].[Answer] 
AFTER INSERT, DELETE 
AS BEGIN
   DECLARE @id as int = 0,
           @count as int = 0;

   SELECT TOP 1 @id = QuestionId FROM inserted; 

   IF @id = 0
    BEGIN
    SELECT TOP 1 @id = QuestionId FROM deleted; 
    END

   SELECT @count = count(*) FROM Answer where QuestionId = @id; 

   UPDATE Question
   SET AnswerCount = @count
   WHERE Id = @id;         
END

我正在做所有这些开销,因为将计数保存在列中并且只在想要显示计数时访问列值而不是每次我们想要显示时都在导航属性(答案)上调用计数函数时效率不高这个问题的答案很重要??

有人可以详细说明这种情况吗?

4

2 回答 2

0

看起来您已决定对数据库进行非规范化以希望提高性能。你知道这会提高性能吗?你做过剖析吗?如果不是,我会先进行规范化,然后仅在您确实遇到性能问题时才考虑重构架构以存储计数。我不确定 SO 做什么或任何其他网站,但我想在走这条路之前确定性能提升。也许其他人会知道并给出一个很好的答案。

如果您认为性能会很差,因为您必须检索每个问题的答案集合,那么这是不正确的。您始终可以将 Linq 写入返回匿名类型(或包含问题、answerCount 对的实际类型)的实体查询。

var query = context.questions.GroupJoin(context.answers,
q => q.QuestionId,
a => a.QuestionId,
(q, aGroup) => new
{
Question = q,
AnswerCount = aGroup.Count()
});

上面将返回一个匿名类型,其中包含一个问题和答案计数,而不具体化答案。如果您愿意,您可以进一步改进它以仅返回匿名类型的问题标题和答案计数。

于 2013-05-01T11:36:51.537 回答
0

好吧,绝对可以肯定,将 AnswerCount 列添加到 Questions 表(非规范化)将提高查询性能;权衡是,当触发器触发时,写入性能会受到打击(它可能只是一个轻微的轻敲,也可能是一个真正的冲击力)SELECT @count = count(*) FROM Answer where QuestionId = @id;。您可以简单地增加或减少问题的 AnswerCount 列中的值,而不是发出此选择,具体取决于它是答案插入还是答案删除。PS 使 AnswerCount 默认值 = 0。

于 2013-05-01T12:41:43.173 回答