Performance 如何实现线程化注释?
我正在开发一个可以支持线程注释的web应用程序。我需要能够根据收到的票数重新安排评论。(与线程注释在中的工作方式相同) 我很想听听SO社区对如何做到这一点的意见 我应该如何设计注释表? 以下是我现在使用的结构: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 这个结构应该做些什么改变 我应该如何从该表中获取详细信息,以便以正确的方式显示它们? (欢迎使用任何语言实现。我只想知道如何以最好的方式实现)
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:附加到特定对象的所有注释的标识符
- 日期:注释日期(允许按顺序获取注释)
- 排名:评论排名(允许按排名获取评论顺序)
·亚历克斯
< 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';