【问题标题】:How can I find all necessary columns for creating a unique index?如何找到创建唯一索引所需的所有列?
【发布时间】:2021-10-25 10:15:28
【问题描述】:

我在 oracle 数据库中有表,在这些表中,有不同数量的列。在表格中,有真实世界的数据(100 万 - 10 亿行) 我想为每个表创建一个唯一索引,但我不知道哪些列或哪些列包含唯一数据。

我们的目标是为一个表找到最少的列,我可以使用这些列创建唯一索引。

我的想法是为每一列创建一个选择语句并检查它有多少不同的值:

select COLUMN_1, count(1) CC from TABLE group by COLUMN_1;

这样,我知道表中的记录数,并通过将其与此查询结果相除,我得到一个表示列唯一性的数字。对所有列执行此操作后,我按列的唯一性顺序列出列,直到每一行都变得唯一。

有没有更好的方法,或者已经存在的算法可以做到这一点?

【问题讨论】:

  • 我会为每个表添加一个生成的唯一 id 列,而不是依赖现有数据的唯一性
  • 表有一个唯一的 id 列,但是对于外键引用我们使用这个唯一索引的列
  • 那么我想你会遇到一些头疼的问题......那么散列所有列的连接怎么样?
  • 使用所有唯一索引的列而不是唯一 ID 是违反我想说的最佳实践的。你有这样做的具体理由吗?
  • 实际上可能没有一组独特的列。按唯一性的顺序将它们堆叠起来也不是正确的做法。

标签: sql oracle


【解决方案1】:

第一件事,是的,这个:

select COLUMN_1, count(1) CC from TABLE group by COLUMN_1;

将为您提供唯一值的计数。此计数与总表计数越接近,您拥有的唯一性就越高。所以这个:

select COLUMN_1, count(1)/n_table_total_count uniqueness_ratio from TABLE group by COLUMN_1;

实际上会给你列数据的 uniqueness_ratio。 1 表示唯一,任何更少都表示没有唯一性。最接近 1 的值越不同。

因此,对所有列运行此命令可以获得所有列的唯一性比率。 如果您有一个或多个值为 1 的列,则可以使用这一列或多列或您喜欢的任何其他组合,并且您有主键。

但是,如果没有列的 uniqueness_ratio = 1,那么您需要再次搜索。也就是说,获取最接近唯一列的 2(或 3 或 4)列并不能保证它们的数据组合是唯一的:

ColA,uniqueness_ratio = 0.9999656743556 ColB, uniqueness_ratio = 0.94632

这些列都有一些具有相同值的行。很少,但他们确实如此。 在 ColA 处具有相同值的行之一也可能在 ColB 处具有相同值。罕见,但可能。所以你需要运行:

select ColA, ColB, count(1)/n_table_total_count uniqueness_ratio from TABLE group by ColA, ColB;

如果 uniqueness_ratio = 1 则此列组合可用作主键。如果没有,您需要另一种组合。

很明显,你需要用一些逻辑来组合,并运行额外的语句来得到一个 uniqueness_ratio = 1。也许这个逻辑可以取最好的 2,如果不是最好的 3,依此类推。其中 'best' = 最接近 uniqueness_ratio = 1,即更高的值。

您将需要大量语句集,因此我建议您创建一个过程来创建可以打印和/或执行的文本(动态 sql)。

请注意,即使所有列都涉及但仍然存在至少 1 个重复行,如果无法实现唯一性,则此方法可能仍然无效。

此方法不能保证以后可以插入数据。如果未来的行违反了选定的主键,它将不会被插入。

您最好考虑使用生成的唯一值作为主键添加新列的选项。这肯定会成功,并且欢迎所有未来的数据。

最后要注意聚类。 Oracle 数据库始终使用主键作为集群键。这意味着在物理上将数据重新排列到磁盘。而且,如果性能是添加主键的根本原因,那么检查分区也是值得的。值得一试,因为添加 PK 不会是一件容易或快速的任务。

【讨论】:

    【解决方案2】:

    识别右列

    要识别正确的列,我通常的技巧是使用 ROW_NUMBER() Oracle Analytic Functions

    使用如下列:

    ROW_NUMBER() OVER (PARTITION BY <column1>[, <column2>...] ORDER BY (SELECT 1 FROM DUAL)) AS <your column name here>
    

    这会生成一个唯一计数。与窗口函数一样,这首先需要一个子查询或一个公共表表达式。然后随后仅选择窗口函数大于 1 的行。 任何这样的行都意味着索引不会是唯一的。

    指数策略

    如果唯一索引中有超过 3 个(大约,取决于)列,或者索引中有超过 5 个字符的字符列,那么最好构建一个代理键,尤其是在数据集有很多行的情况下。 如果是整数或大整数类型,则该键更容易遍历。

    在主代理键上以正确的顺序(或多个非唯一索引)构建单独的唯一索引以方便查询。

    【讨论】:

      猜你喜欢
      • 2021-01-12
      • 2010-09-15
      • 1970-01-01
      • 2020-09-01
      • 2017-02-28
      • 1970-01-01
      • 2012-05-09
      • 2021-12-15
      • 2010-09-16
      相关资源
      最近更新 更多