识别 PostgreSQL 中潜在主键/外键关系的算法方法

问题描述 投票:0回答:1

我在 PostgreSQL 中有很多表,每个表有很多列。我需要编写一个程序来识别可能成为潜在主键和外键对的列。

我正在迭代每个组合并根据不同的数据比较列。伪代码:

for (int i=0;i<cols.size;i++)
{
   for (int j=0;j<cols.size;j++)
   {
      if (i != j && (isNotAlreadyVisited(i,j) && isNotAlreadyVisited(j,i)))
      {
         QueryDistinctDataAndCompareCols(i,j)
      }
   }
}

在 QueryDistinctDataAndCompareCols() 方法中,我获取两个列作为集合的不同值,并获取列之间的不匹配计数,据此我得出一个分数,表示它们是否有资格成为 PK-FK 对。

当列太多、表太多时,迭代次数会花费太多时间。我还必须在每次迭代中查询数据库以获得列的不同值。

应用程序层或数据库层中更快且可扩展的解决方案是什么?

在某些情况下,列和表的数量可能分别超过 5000 和 1000,每列超过 5000 个不同值。

如果我必须在开始此处理之前预先计算派生数据,这是可以接受的。

postgresql foreign-keys primary-key
1个回答
0
投票
  1. 四处询问文档。有人构建了这些表,有可能有一个文档、一个存储库、一个脚本,某人的

    .psql_history
    可以告诉你什么是什么。

  2. 这个问题听起来像是您正在处理一组没有任何约束的表,但没有明确说明,因此可能值得检查一下

    pg_constraint

  3. 假设上述两种方法都失败了,除了您现在正在做的事情之外,实际上没有其他方法可以做到这一点:提取并比较每列的计数和不同值或其组合。有像 Dataiku 这样的工具可以帮助进行探索性分析。

  4. 这些工具可以加快速度,而您自己可以做的只是示例。您可以提取 1000 行或更少的行,并消除已经基于该小子集的大多数非唯一列:

    with samples as (select * from t1 limit 100),
    select c1,c2,c3,c4,count(*) from samples 
    group by cube(c1,c2,c3,c4) having count(*)>1;
    

    group by cube ()
    可让您检查所有字段组合的计数。这使得每个表中只剩下几列作为 PK 的潜在候选者。

  5. 一旦您有了一些 PK 候选者,您就可以迭代

    information_schema.columns
    并尝试定义主键和外键工作所需的
    unique constraint
    ,然后记下允许您这样做的组合,丢弃那些报告
    ERROR:  could not create unique index "c1c2" DETAIL:  Key (c1, c2)=(3, 3) is duplicated.

    的内容
  6. 一旦你有了PK,你就可以在其他表中寻找它们

    select count(*) from t1 where exists (select from t2 where t1.nonpk=t2.pk);
    

完成后,请确保设置适当的约束以在 DDL 中巩固所有这些并记录下来。

© www.soinside.com 2019 - 2024. All rights reserved.