将计算值存储在数据库中是一个坏主意吗?

Ami*_*adi 2 sql database sql-server database-design relational-database

假设我正在开发一个在线商店项目。因此,我必须在数据库中创建一个名为“Product”的表。假设我还希望用户能够“喜欢”我的产品。这需要我创建另一个名为“ProductLike”的表来存储用户的 ID 以及他们喜欢的产品的 ID(联结表)。

主要场景:每次用户向我的网站发送请求以获取产品页面时,我都必须重新计算该产品的点赞数。

我的问题是:所以,我知道标准方法不是将“计算值”存储在数据库中(规范化)。但像这样的案例呢?(我的意思是计算某些东西可能会很昂贵的情况)。例如,在上面的示例中,在“Product”表中拥有一个名为“NumberOfLikes”的列来存储计算出的产品点赞数以便快速检索不是更好吗?

Zoh*_*led 5

更新

在“Product”表中拥有一个名为“NumberOfLikes”的列来存储计算出的产品喜欢数不是更好吗?

恕我直言,这个问题的直接答案是“不,除非你由于点赞计数而遇到真正的性能问题”。

如果确实存在性能问题,并且已将其来源确定为点赞数,那么您可能需要考虑LikesCountproducts表中添加一列。如果您确实添加了这样的列,请注意您必须在表的每次更改时更新它ProductLike- 删除、更新和插入。
这意味着您必须为此表编写一个触发器来处理所有这些情况,但这应该不会太难,因为您可以在单个触发器中完成所有操作 - 如下所示:

create trigger ProductLikeChaneged on ProductLike 
for insert, update, delete
as

    update p
    set LikesCount = (select count(*) from ProductLike as pl where pl.productId = p.Id)
    from product as p
    where exists
    (
        select 1 from inserted as i where p.id = i.productId
    )
    or exists
    (
        select 1 from deleted as d where p.id = d.productId
    )
Run Code Online (Sandbox Code Playgroud)

原始版本
根据您的描述,“计算”产品的点赞数只是表中的行数,ProductLike其中产品 ID 是您当前向用户显示的产品的 ID。
这可以非常快地完成,特别是如果ProductLike表聚集索引是ProductId然后UserId,从而允许 SQL Server 使用聚集索引查找而不是表扫描。

基本上,您的ProductLike表格应该如下所示:

 Create table ProductLike
 (
     ProductId int,
     UserId int,
     Constraint PK_ProductLike PRIMARY KEY (ProductId, UserId)
 )
Run Code Online (Sandbox Code Playgroud)

请注意,默认情况下,SQL Server 将使用主键作为表的聚集索引。

那么产品页面的选择语句可以是这样的:

select Name, Description, -- Other product related details
       (select count(*) 
        from productLike as pl 
        where pl.ProductId = p.Id) as likeCount
from product as p
Run Code Online (Sandbox Code Playgroud)