在oracle

时间:2016-01-28 06:55:14

标签: oracle database-design

让我以最好的方式解释我正在努力解决的问题。

我们的客户想要一个票务系统。该系统必须为每张票提供严格的序号。每天票证号码将被重置为0.此外还有一个与票证相关联的service_id,这是一个棘手的部分,每个服务都有自己的序列号。当然,服务变化很大,因此对于每个服务都有不同的顺序,在可管理性方面似乎不是最好的方法。

此外,有一段时间新票证的并发性非常高,因此查询最大值(ID)+ 1对于他们需要的速度目标来说可能太慢(几乎是即时的)。

有什么想法吗?对不起,没有代码,我正处于项目的初期阶段,需要对这个问题有一个好的方法。

2 个答案:

答案 0 :(得分:1)

也许这可能是一种方法:

构建如下表格,以存储用于每项服务的票证

create tabe tickets ( service_id ..., ticket ..., date ...)

使用以下过程获取给定服务的票号,并​​在表中存储每个服务使用的最后一个号码(伪代码):

procedure get_ticket( p_service_id IN ..., po_ticket OUT ...) is
    pragma autonomous_transaction   

   /* search the service_id to see if it's already used */
   begin 
       select ticket, date into vTicket, vDate from tickets where p_service_id = service_id
   exception
     when NO_DATA_FOUND then vTicket := null; vDate := null
   end

   if vTicket is null and vDate is null then
       /* the service never had a ticket */
       vTicket := 0
       insert into tickets values ( p_service_id, vTicket, sysdate)       
   else
       if vDate = sysdate then
           /* the service already had a ticket today, need to increment */
           vTicket := vTicket + 1
           update tickets set ticket = vTicket where service_id = p_service_id
       else
           /* the service already had a ticket, but before today; need to set to zero */
           vTicket := 0
           update tickets set ticket = vTicket, date = sysdate where service_id = p_service_id
       end if;
   end if

   po_ticket := vTicket
   commit
end

通过这种方式,您应该能够存储用于给定日期的每项服务的票证,而无需扫描更大的表格来搜索所使用的最大值

必须以某种方式完成此操作以通过使用显式LOCKFOR UPDATE查询或任何其他方式来处理并发,具体取决于最适合您的需求以及您可以/不能对数据库执行的操作。< / p>

答案 1 :(得分:1)

解决此问题的一种方法是按需计算顺序票证ID,而不是存储它。我们假设您的表格看起来像tickets (id, service_id, ticket_date, other_columns)。对id使用单个序列,不要将其回滚,让它成为主键。这样你就不会关心差距,交易等等,Oracle会为你处理这一切。

稍后,当您确实需要给定票证的序号时(让我们说id = :N),请使用类似这样的查询:

select count(t2.id) from tickets t1, tickets t2
where t1.id = :N
and t2.ticket_date = t1.ticket_date
and t2.service_id = t1.service_id
and t2.id <= t1.id

id上创建主键并在ticket_date, service_id, id上创建唯一索引可以大大加快此查询速度,即使对于大型表,也只需要几分之一秒来计算ID。您可以将它包装在一个函数中,并在任何您喜欢的地方使用它,例如将其放入视图并根据需要进行查询。

如果您需要为某个日期提供给定service_id的所有顺序键,那么功能可能太慢(但是,先测试它!Oracle在处理大量数据时可能会非常惊人)。如果它毕竟要慢,你可以使用包含分析row_number()函数的查询的视图,如下所示:

select row_number() over(partition by t.ticket_date, t.service_id order by t.id) seq_no,
       t.* 
  from tickets t

索引建议仍然适用于此。请注意,在针对此类视图构建查询时,您必须至少包含ticket_date才能通过变换器进行优化并表现良好 - 请记住,EXPLAIN PLAN是您的朋友!

相关问题