Postgresql 按主-明细关系排序表

Postgresql 按主-明细关系排序表,postgresql,Postgresql,每次启动单元测试时,我都需要删除所有表中的所有数据。现在我正在使用 为测试套件中包含的每个表截断表“TABLE_name”级联 问题是这些查询需要很多时间——大约9-11秒 我希望能够用TRUNCATE语句替换那些TRUNCATE…CASCADE,但要做到这一点,我需要一个表列表,这些表按照主-细节(父-子)关系排序(子项优先)。我可以手动创建这样的列表一两次,但数据库每天都在变化。有没有办法按这种顺序生成表列表 我使用的是Postgresql。解决这个问题的方法如下: 延迟所有可延迟的约束并忽

每次启动单元测试时,我都需要删除所有表中的所有数据。现在我正在使用
为测试套件中包含的每个表截断表“TABLE_name”级联

问题是这些查询需要很多时间——大约9-11秒

我希望能够用
TRUNCATE
语句替换那些
TRUNCATE…CASCADE
,但要做到这一点,我需要一个表列表,这些表按照主-细节(父-子)关系排序(子项优先)。我可以手动创建这样的列表一两次,但数据库每天都在变化。有没有办法按这种顺序生成表列表


我使用的是Postgresql。

解决这个问题的方法如下:

  • 延迟所有可延迟的约束并忽略它们。不能有效地在不可延迟外键中包含循环,因为没有满足它们的插入顺序

  • 我将构建一个存储过程,它将查找可延迟的外键并将它们全部延迟。这是相对琐碎的

  • 我将构建一个CTE,该CTE将构建一个外键约束树,然后按照路径长度的顺序反向搜索它们,以便第一个表将是具有最多表的表,这取决于它们的键

  • 然而,这可能是矫枉过正。只有两个功能可能更容易:

  • 函数1查看类中的每个关系,并针对每个关系发布:

    EXECUTE$e$ALTER TABLE$e$| | quote_ident(relname)| |$e$disable trigger all$e$

  • 功能2的作用与此相反:

    EXECUTE$e$ALTER TABLE$e$| | quote_ident(relname)| |$e$enable触发所有$e$


  • 在清除过程开始时调用函数1。在提交之前调用函数2。

    如果您尚未使用PostgreSQL 9.2,则可能需要阅读并尝试更新到它。究竟有多少个表在<代码> >截断< /代码> D,这里只是一个注释,但是您应该真正考虑更好地隔离单元测试。他们不应该真的碰数据库。对数据库进行写操作的集成(又称功能)测试是一种很好的做法。但是,它们通常作为CI服务器的一部分运行,然后它们是否需要额外的几秒钟来运行并不重要(因为这不会影响开发人员的工作)。再说一次,答案不在哪里。只是一个评论和一个建议,也许还有一些值得思考的东西。祝你好运。这些测试在CI服务器上运行。也许我不应该称之为单元测试。他们实际上应该测试数据库。我通过编写一个自定义应用程序来解决这个问题,该应用程序查询数据库中的表和外键,并创建TRUNCATE语句。我已经将运行整个套件所需的时间从20分钟减少到了11分钟。你能写一个简短的答案并将其作为答案发布,这样它就可以被提升或接受吗?不幸的是,我不能,因为我不再有这个代码(我已经改变了工作地点)。解决方案可以在15分钟内编码-查询表和外键,然后根据外键的信息对表进行排序。如果模式有循环(例如,表A指向B,B指向A,当然更长的循环也会破坏事情),那么这不起作用。如果模式可以修改,那么您的方法肯定是一个好方法。我要求不能修改模式(这是一个银行项目,所以我的PM不打算冒这个解决方案出问题的风险)。另一件事是:你测试过这个速度吗?禁用触发器会更快。注意,这实际上并没有修改模式,而是暂时禁用触发器。触发器仍然存在,但它们不会在禁用和启用之间运行。