2013-07-29 19 views
2

我有一个包含三个相关的列tickets一个表:idstartfinish其中startfinishtimestampsquering的时候,SQL性能间隔

我有第二张表(intervals)只有一个相关的列是time pointtime_point也是timestamptime_point总是每15分钟一班。这是第二张表的内容是:

8:00 
8:15 
8:30 
... 

第一张表(票)有4百万记录。第二个只有96个记录(24 * 4)。

我必须选择多少张门票在任何time_point

我写了下面的查询是开放的:(简体版)

select * 
from interval, ticket 
where (finish is null or finish > time_point) 
     and start < time_point 

其作品,但实在是太慢了。问题是两个表之间没有真正的连接,我认为每行都会执行全表扫描。

我该如何在这里获得更好的表现?

谢谢!

编辑:这是一个Oracle数据库。加快这

+0

我怀疑,这个查询在各种情况下工作。 'start

+1

如果你真的需要简单的(可计算的)时间间隔,则应该将“完成”截断到第一个早期的15分钟标记。如果您需要更通用的方法,我会尝试使用区间表来说明区间的开始和结束,并加入'ticket.finish> = interval.start和ticket.finish

+0

你正在使用什么数据库系统? –

回答

1

我相信你不需要交叉连接或创建间隔表。 而是尝试以下操作:

> select count(*), tsd from (
>   select 
>   /**************************************************************** 
>   Now 
>   1- bring your finish column into the format you need: HH24:MI 
>   2- truncate its content down to the interval the row belongs to 
>   ****************************************************************/ 
>   to_char(dt,'HH24')|| decode(trunc(to_char(dt,'MI')/15) * 15,0,'00',trunc(to_char(dt,'MI')/15)*15) 
> tsd 
>   from (
>    select nvl(finish ,to_date('31.12.2999', 'dd.mm.yyyy')) dt  -- 
>    from tickets 
>    /**************************************************************** 
>    Now Filter out your tickets(before truncate), to find the relevant 
>    tickets for your period use a Parameter date and compare it to the 
>    start and end columns nvl(finish ,to_date('31.12.2999', dd.mm.yyyy')) 
>    ****************************************************************/ 
>    where P_YOUR_PARAM_DATE between start 
>          and nvl(finish ,to_date('31.12.2999', 'dd.mm.yyyy')) 
>   ) dat 
>  ) group by tsd order by tsd ; 
0

一种方法是包括在一个综合指数结束列,因此没有必要从表中读取来获取该值:

   create index IX_Tickets on Tickets(start,finish) 

附:删除Tickets.start中的任何简单索引。

P.P.S.请澄清:您的intervals表中的8:00, 8:15表不是timestamp数据类型。为了简单起见,你是否在你的问题中排除了日期元素?

+0

是的,我做到了。这是表格和查询的简化版本。 – Luixv

+0

不要“简化”查询。如果Ticket.start实际上是一个包含日期和时间块的时间戳,则为您指定的日期时间范围创建一个包含日期元素(使用CTE,如果可用)的实际时间表的表格,然后将这些时间段与Ticket.start和Ticket.finish。综合指数将有所帮助。 – Tim