【问题标题】:Oracle Partitioned SequenceOracle 分区序列
【发布时间】:2010-02-15 10:58:47
【问题描述】:

我正在尝试查看是否存在创建具有分区逻辑的序列的东西。 我需要一个依赖于其他主键 ex 的序列号:

id_person   sequence id
        1 | 1
        1 | 2
        2 | 1
        3 | 1
        1 | 3

所以序列必须依赖于id_person 分区。 oracle上有这样的东西还是我必须自己在应用程序级别实现它?

谢谢。


您好,已经创建了这个 PLSQL 包一个函数和过程:

PROCEDURE INIT_SEQUENCE(NAME varchar2, pkColumnNameList PARTITIONED_SEQUENCE_PK_COLUMN);
FUNCTION GET_NEXT_SEQUENCE_VALUE(NAME varchar2, pkPartitionColValue PARTITIONED_SEQUENCE_COL_VALUE) RETURN NUMBER;

INIT_SEQUENCE - 输入要在序列中关联的名称和列名列表,这些列名是固定序列的固定主键部分 Ex:'ID_PERSON'

此过程的工作是创建将根据 pkColumnNameList 列管理序列增量的表。

GET_NEXT_SEQUENCE_VALUE- 获取要递增的序列名称和 pkColumnNameList 主键的值,然后进行下一步: 1)动态创建sql来工作 2) dbms_lock.allocate_unique();锁定表 3) 检查表中是否存在输入中 pk 值的记录 4) 如果存在记录,则在序列列中使用 max + 1 更新记录 5)如果记录不存在,则在序列列中插入带有 1 的新记录 6)返回新的id;

我想提前收到对此的评论...

【问题讨论】:

  • 您能详细说明什么是序列 ID 列吗?
  • 1-10 或 100,000 的人 ID 会有多少... 可以有差距吗?如果只有几个人 ID,只需制作 n 个序列 - 也就是说,如果允许有间隙。不要注意那些吐槽并发问题的人,显然这不是一个严肃的应用程序,有数百个同时连接插入到这个表中。是吗?
  • 好吧,这里有点讽刺,但总的来说我是认真的。人们在询问您期待多少插入之前开始抱怨并发。如果你每小时有 10 次插入,wtf 关心吗?
  • person_id 仅作为示例。我的意见是优化序列号 id'like 有,就像在上面的例子中,由 fir 部分主键分区排序的序列,在这个例子中分区是由 id_person 管理的,但这只是一个例子。

标签: sql database oracle


【解决方案1】:

实际要求二级序列无空位吗?如果是这样,你就有了一个巨大的序列化/可扩展性问题。

如果您需要呈现供人类消费的无间隙序列,您可以使用 Nick Pierpont 建议的实际序列(或时间戳)并保持可扩展性,您可以使用分析函数。

数据集(t1):

 ID_PERSON SEQUENCE_ID
---------- -----------
         1           1
         2           2
         3           3
         1           4
         1           5
         1           6
         2           7
         3           8
         1           9

SQL:

select * 
  from 
  (select id_person, 
          sequence_id as orig_sequence_id,         
          rank () 
            over (partition by id_person 
                  order by sequence_id) 
            as new_sequence_id
     from t1
  )
 order by id_person, new_sequence_id;

结果:

ID_PERSON  ORIG_SEQUENCE_ID NEW_SEQUENCE_ID
---------- ---------------- ---------------
         1                1               1
         1                4               2
         1                5               3
         1                6               4
         1                9               5
         2                2               1
         2                7               2
         3                3               1
         3                8               2

【讨论】:

  • +1,很好的解决方案。避免存储二级序列及其随之而来的维护/性能问题。
  • 巨人?一个巨大的序列化问题......每天插入 10 条记录?这个数字是从哪里来的?我编造了,就像您必须确定是否存在真的即将发生的并发问题。他可能有也可能没有并发问题。
  • @Stephanie Page:引入序列化的设计无法扩展。要么它是一个玩具应用程序,要么最终,序列化将咬住使用“select max(column) + 1”“模式”的设计。首先不引入序列化要容易得多。
【解决方案2】:

恐怕你必须这样做:

INSERT INTO t
(
  id_person,
  sequence_id
)
VALUES
( 
  <your_person_id>,
  ( SELECT 1 + NVL( MAX( sequence_id ), 0 )
    FROM t
    WHERE t.id_person = <your_person_id>
  )
)

【讨论】:

  • 感谢您的想法,我正在尝试实现一个包 pl-sql 来制作这种序列
  • 您需要处理 2 个用户同时尝试插入的情况 - 一个会因 PK 违规而失败。
  • 为什么不直接使用正常的序列而不让它依赖于人呢?如果需要,您仍然可以向客户端应用程序提供与个人相关的订单号。
  • @Tony Andrews:绝对正确。我试图通过将INSERT 放入一个过程并在DUP_VAL_ON_INDEX-exception 处理块中递归调用它来避免这个问题。由于第二个INSERT 被第一个事务阻止,因此第二次尝试成功。不过,没有什么值得骄傲的……有什么建议吗?
  • @nick 如果我可以选择我更喜欢放置有序序列,在插入中也有点慢,但在读取中我可以有更简单的选择
【解决方案3】:

您要查找的不是 sequence,正如 Oracle 文档所声称的那样:“序列生成器提供了一系列连续的数字”

您正在寻找一个依赖于另一个的计算字段,在本例中是主键。正如其他人建议的那样,您需要在代码中添加逻辑。这意味着在procedureinsert 句子中。

【讨论】:

  • 我创建了一个 olsql 包来管理这种 od 序列并使用 dbms_lock 来执行对并发性的控制。该序列的每一种都有一个表cor计算。今天晚些时候,我将在这篇文章中发布代码,我想分享这个想法,看看它是否设计得很好
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
  • 1970-01-01
相关资源
最近更新 更多