Performance 如何实现线程化注释?

Performance 如何实现线程化注释?,performance,database-design,comments,query-optimization,table-structure,Performance,Database Design,Comments,Query Optimization,Table Structure,我正在开发一个可以支持线程注释的web应用程序。我需要能够根据收到的票数重新安排评论。(与线程注释在中的工作方式相同) 我很想听听SO社区对如何做到这一点的意见 我应该如何设计注释表? 以下是我现在使用的结构: Comment id parent_post parent_comment author points 这个结构应该做些什么改变 我应该如何从该表中获取详细信息,以便以正确的方式显示它们? (欢迎使用任何语言实现。我只想知道如何以最好的方式实现)

我正在开发一个可以支持线程注释的web应用程序。我需要能够根据收到的票数重新安排评论。(与线程注释在中的工作方式相同)

我很想听听SO社区对如何做到这一点的意见

我应该如何设计注释表? 以下是我现在使用的结构:

Comment
    id
    parent_post
    parent_comment
    author
    points
这个结构应该做些什么改变

我应该如何从该表中获取详细信息,以便以正确的方式显示它们? (欢迎使用任何语言实现。我只想知道如何以最好的方式实现)

在实现此功能时,我需要注意哪些方面,以减少CPU/数据库的负载


提前感谢。

在数据库中存储树是一个有许多不同解决方案的主题。这取决于您是否也要检索子层次结构(也就是项X的所有子项),或者您是否只想获取整个层次结构集,并使用字典在内存中以O(n)方式构建树

您的表的优点是,通过在parentpost上进行筛选,您可以一次性获取帖子上的所有评论。由于您已经用教科书/朴素的方式定义了注释的父级,因此必须在内存中构建树(见下文)。如果要从数据库中获取树,则需要另一种存储树的方法: 请参见我对基于预计算的方法的描述: 或通过:

或者另一种方法:

如果在内存中获取层次结构中的所有内容并在其中构建树,那么由于查询非常简单,因此效率会更高:select。。来自注释,其中ParentPost=@id ORDER BY ParentComment ASC


在该查询之后,只需使用一个字典在内存中构建树,该字典跟踪元组CommentID-Comment。现在,您可以遍历结果集并动态构建树:您遇到的每个注释都可以在字典中查找其parentcomment,然后将当前处理的注释也存储在该字典中

您当前的设计基本上适用于小型层次结构(少于1000项)

如果要获取某个特定级别或深度,请向结构中添加一个“级别”项,并将其作为保存的一部分进行计算


如果性能有问题,请使用适当的缓存

我会在上面的选项卡中添加以下新字段:

  • 线程id:附加到特定对象的所有注释的标识符

  • 日期:注释日期(允许按顺序获取注释)

  • 排名:评论排名(允许按排名获取评论顺序)

使用这些字段,您将能够:

  • 在单个操作中获取线程中的所有注释
  • 按日期或等级在线程中排序注释
  • 不幸的是,如果您想将查询数据库保留在接近SQL标准的位置,就必须在内存中重新创建树。一些数据库为分层数据提供特殊查询(如Oracle)


    ·亚历克斯

    < P>两件事也要考虑…

    1) 当你根据排名或日期说“像reddit一样排序”时,你指的是顶级还是全部

    2) 删除节点时,分支会发生什么情况?你是他们的父母吗?在我的实现中,我认为编辑器会做出决定——要么隐藏节点并将其与可见子节点一起显示为“comment hidden”,要么隐藏注释及其子节点,要么核化整个树。重新建立父子关系应该很容易(只需将孩子的父项设置为已删除的父项),但涉及整个树的任何内容似乎都很难在数据库中实现

    我一直在看PostgreSQL的模块。它应该使涉及部分树的数据库操作更快一些。它基本上允许您在表中设置一个字段,如下所示:

    ltreetest=# select path from test where path <@ 'Top.Science';
                    path                
    ------------------------------------
     Top.Science
     Top.Science.Astronomy
     Top.Science.Astronomy.Astrophysics
     Top.Science.Astronomy.Cosmology
    

    如果与使用存储过程的传统“comment\u id”/“parent\u id”方法相结合,我认为您可以实现这两个方面的最佳效果。您可以使用“路径”快速遍历数据库中的注释树,并且仍然可以通过“注释id”/“父项id”确保引用完整性。我的设想是:

    CREATE TABLE comments (
    comment_id SERIAL PRIMARY KEY,
    parent_comment_id int REFERENCES comments(comment_id) ON UPDATE CASCADE ON DELETE CASCADE,
    thread_id int NOT NULL  REFERENCES threads(thread_id) ON UPDATE CASCADE ON DELETE CASCADE,
    path ltree NOT NULL,
    comment_body text NOT NULL,
    hide boolean not null default false
    );
    
    注释的路径字符串类似于be

    <thread_id>.<parent_id_#1>.<parent_id_#2>.<parent_id_#3>.<my_comment_id>
    
    要隐藏节点“3”及其子节点,请发出以下命令:

    UPDATE comments SET hide=true WHERE path @> '102.1.3';
    

    但我不知道——这可能会增加不必要的开销。另外,我不知道ltree的维护情况如何。

    Alex,谢谢你的回答,但我不明白你的一些观点。我认为线程id和post id是一样的,日期可以被一个自动递增的id替换,秩=点。这就是我在设计中所做的。你能澄清一下我的设计和提议的设计有什么不同吗?@Niyaz:我想你可能需要修改你的问题,因为我没有看到帖子id(事实上我误解了要点)。thread_id:线程中所有注释的唯一id(附加到一段内容)。autoincrement可以提供订单,但不等同于日期(检查几乎所有论坛)。我很困惑。如果“parent\u comment”指向家长的注释id,我会将其命名为“parent\u comment\u id”以澄清问题。我不知道“家长帖子”是什么意思,为什么它不同于“家长评论”。家长帖子指的是原始帖子(不是任何评论)。我认为它可以让我通过一个查询获得与帖子相关的所有评论,而不是通过父子评论结构进行递归。@Niyaz:据我所知,父帖子相当于线程id。因此,看起来剩下的要添加的内容只有:日期、用户详细信息(如果需要)“我不懂等级?”Yasarafath他的意思是每一条评论都应该知道它在树上有多深。例如,这允许您仅查询前3个级别。只有当用户展开注释树时,其余的注释才会加载我在三年前问过这个问题,谢谢你的回答“内存中”你是说在应用程序级别
    <thread_id>.<parent_id_#1>.<parent_id_#2>.<parent_id_#3>.<my_comment_id>
    
    102.1.3.31
    102.1.3.54
    
    UPDATE comments SET hide=true WHERE path @> '102.1.3';