【问题标题】:Is PostgreSQL's Ltree module a good fit for threaded comments?PostgreSQL 的 Ltree 模块是否适合线程注释?
【发布时间】:2010-10-10 20:57:47
【问题描述】:

我正在考虑在我的应用程序中使用 PostgreSQL 的 Ltree module 来帮助处理线程化 cmets。我一直在关注它用于螺纹 cmets。我认为它会在您需要更新节点及其子节点的情况下有所帮助,例如当您想要隐藏评论及其回复时。

我认为 ltree(或类似的东西)如果与传统的邻接列表(“comment_id”/“parent_comment_id”)结合使用会很有用。

在开始使用 ltree 之前,我想知道一些事情:

  1. 您是否或曾经使用过 ltree?这就是所谓的“生产就绪”吗?
  2. 如果是这样,您用它解决了哪些问题?做得好吗?
  3. 您认为它适合 线程评论系统?
    1. 如果你使用它,你在路径的“文本”部分使用了什么?您是否设置了类似于他们使用“Top.Astronomy.Cosmology”的 DMOZ 示例或基于主键“1.403.29.5”之类的东西?
    2. 有没有更好的方法来做到这一点?使用嵌套列表方法我有点紧张——我读过的所有内容都表明,UPDATES 或 INSERTS 并不是很热(你不必重新排序整个事情吗?)。我也不是 CS 专业的,这种数据结构是我将来可能会忘记的东西。有人在使用 cmets 或类似的嵌套列表吗?

如果有任何帮助,这是我正在考虑的架构:

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
);

ltree 使用的“路径”列如下所示:

<thread_id>.<parent_comment_id_#1>.<parent_comment_id_#2>.<my_comment_id>

在路径中使用主键有什么问题吗?我应该在路径中包含节点自己的主键吗?如果我这样做了,在其上放置唯一索引作为约束是否有意义?

【问题讨论】:

  • ltree 是一个“物化路径”实现。请参阅dbazine.com/oracle/or-articles/tropashko4 以比较可能的解决方案,包括更便携(但效率较低)的方法,例如嵌套集。
  • 请随意添加这个作为答案。我对其他想法持开放态度。我研究过嵌套集合,但它们似乎很难实现,而且更新/插入速度相当慢(您不必将所有内容都向下移动吗?)。
  • 哦,我正在考虑使用 ltree 除了邻接列表。因此“comment_id”和“parent_comment_id”。我的想法是使用 ltree 来加速分支上的操作
  • 请记住,8.4 会将其中的一些功能引入核心(请参阅developer.postgresql.org/pgdocs/postgres/queries-with.html),因此如果您要修改现有代码,您可能希望推迟到 8.4 发布。
  • 将此作为答案,对我来说听起来很像。我可能会推迟...我喜欢新的 postgresql 版本——我总是觉得自己像个糖果店里的孩子 :-)

标签: database postgresql tree comments hierarchy


【解决方案1】:
  1. 是的,是的;
  2. 知识库中部分的层次结构(实现之一);
  3. 是的;

有问题的表之一的定义:

                                                   Table "knowledgebase.section"
           Column           |           Type           |                                  Modifiers
----------------------------+--------------------------+-----------------------------------------------------------------------------
 section_sid                | integer                  | not null default nextval('knowledgebase.section_section_sid_seq'::regclass)
 section                    | character varying        | not null
 description                | character varying        |
 path                       | ltree                    | not null
 is_active                  | boolean                  | not null default true
 role_sid                   | integer                  | not null
 last_modified_by           | integer                  | not null
 creation_datetime          | timestamp with time zone | not null default now()
 last_modification_datetime | timestamp with time zone | not null default now()
 is_expanded                | boolean                  | not null default false
 section_idx                | tsvector                 |
Indexes:
    "section_sid_pkey" PRIMARY KEY, btree (section_sid)
    "section_section_key" UNIQUE, btree (section)
    "idxsection_idx" gist (section_idx)
    "path_gist_idx" gist (path)
Foreign-key constraints:
    "last_modified_by_fkey" FOREIGN KEY (last_modified_by) REFERENCES "user"."role"(role_sid) ON UPDATE CASCADE ON DELETE RESTRICT
    "role_sid_fkey" FOREIGN KEY (role_sid) REFERENCES "user"."role"(role_sid) ON  UPDATE CASCADE ON DELETE RESTRICT
Triggers:
    section_idx_update BEFORE INSERT OR UPDATE ON knowledgebase.section FOR EACH ROW EXECUTE PROCEDURE tsearch2('section_idx', 'section')

“路径”列使用主键作为标签。

该表的当前内容示例(关于主键和“路径”列):

  section_sid | path
 -------------+-------
           53 | 34.53
           56 | 56
           55 | 29.55
           35 | 35
           54 | 34.54
           37 | 30.37
          ... | ...

【讨论】:

  • 字符串的路径是什么样的?你用的是文字还是数字?
  • 如何让路径包含自己的 id,因为它是在插入时计算的?您是否使用触发器、UPDATE 或其他方式?
【解决方案2】:

我建议任何在 SQL 中实现层次关系的人阅读 Joe Celko's Trees and Hierarchies in SQL for Smarties

仅使用 parent_id 时,遍历任意深度的父子链接可能非常低效。这本书描述了使这种访问速度更快的技术。

在本系列文章中也可以免费找到一个策略(我碰巧使用):

【讨论】:

    【解决方案3】:

    PostgreSQL 8.4 版将通过WITHWITH... RECURSIVE 表达式将公用表表达式功能引入核心。如果您正在修改旧代码,您可能需要等到 8.4 发布,这样您就不必担心 Ltree 和新核心语法之间的任何不兼容性。如果您正在使用旧代码,或者不想等待 8.4,您可能需要确保编写的代码易于转换为新语法,尤其是在您更改旧模式或设计新模式时一个。

    另见:

    【讨论】:

    • 这非常非常酷。 WITH 的东西看起来不仅对 cme​​ts 有用。查找标签及其相关标签似乎是另一个不错的选择,因为它正在执行一些自连接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    相关资源
    最近更新 更多