我正在尝试确定完成多线程应用程序的一组进程所花费的总时间,该多线程应用程序在表中跟踪开始和结束时间。描述我的问题的最简单方法是举个例子。
这是我正在使用的表格的精简版(我们称之为进程
):
| id | start_date | end_date |
---------------------------------------------------
| 1 | 07/15/2011 12:00:00 | 07/15/2011 12:01:00 |
| 2 | 07/15/2011 12:00:00 | 07/15/2011 12:02:00 |
| 3 | 07/15/2011 12:00:00 | 07/15/2011 12:03:00 |
| 4 | 07/15/2011 12:01:00 | 07/15/2011 12:05:00 |
| 5 | 07/15/2011 12:01:00 | 07/15/2011 12:03:00 |
| 6 | 07/15/2011 12:03:00 | 07/15/2011 12:04:00 |
| 7 | 07/15/2011 12:03:00 | 07/15/2011 12:07:00 |
| 8 | 07/15/2011 12:03:00 | 07/15/2011 12:06:00 |
| 9 | 07/15/2011 12:04:00 | 07/15/2011 12:05:00 |
| 10 | 07/15/2011 12:05:00 | 07/15/2011 12:07:00 |
| 11 | 07/15/2011 12:08:00 | 07/15/2011 12:09:00 |
有了这么小的数据样本,就很容易将其可视化(我假设一个线程可以完成一个进程并立即拿起下一个进程,而对于这个问题的目的没有任何开销)
12:XX: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
Thread1: 1---4---------------10------] 11--]
Thread2: 2-------] 6---9---]
Thread3: 3-----------7---------------]
Thread4: 5-------8-----------]
从那里您可以很容易地看出花在 11 个过程上的总时间是 8 分钟。
出现问题是因为我正在处理数千条记录,并且有一些时间段根本没有发生任何处理。
如何使用从表中选择的 PL/SQL 查询获得此结果?
最佳答案
这是您可以采用的一种方法。生成可能时间的列表(在您的情况下,一直到秒)并使用“存在”或将其加入您的表以获取每个 ID 的秒数。
*编辑:使用 exists 而不是 Join 的新示例.. 更符合查询试图回答的问题..(至少有一个事件进程在运行多少秒。 .?).在查询下方设置数据...* '
select count(time1) from
(
/* All possible seconds in the time frame you want to track */
select trunc(sysdate) + level/(24*60*60) time1
from dual
connect by level <= (trunc(sysdate)-trunc(sysdate-1))*24*60*60
) all_times
where exists (
/* Atleast one process is running at that second...*/
select 1
from t1
where t1.start_time < all_times.time1
and t1.end_time >= all_times.time1
)
Count(time1)
11
为了便于理解,我只取了4个案例/录音。前三个记录相交,最后一个是完全不相交的记录。
create table t1(
id number,
start_time date,
end_time date
);
SQL> insert into t1 values ( 1,
2 to_date('07/15/2011 12:00:00','MM/DD/YYYY HH24:MI:SS'),
3 to_date('07/15/2011 12:00:05','MM/DD/YYYY HH24:MI:SS'));
1 row created.
SQL> insert into t1 values ( 1,
2 to_date('07/15/2011 12:00:02','MM/DD/YYYY HH24:MI:SS'),
3 to_date('07/15/2011 12:00:04','MM/DD/YYYY HH24:MI:SS'));
1 row created.
SQL> insert into t1 values ( 1,
2 to_date('07/15/2011 12:00:03','MM/DD/YYYY HH24:MI:SS'),
3 to_date('07/15/2011 12:00:06','MM/DD/YYYY HH24:MI:SS'));
1 row created.
SQL> insert into t1 values ( 1,
2 to_date('07/15/2011 12:00:15','MM/DD/YYYY HH24:MI:SS'),
3 to_date('07/15/2011 12:00:20','MM/DD/YYYY HH24:MI:SS'));
1 row created.
SQL> commit;
alter session set NLS_DATE_FORMAT = "MM/DD/YYYY HH24:MI:SS";
SQL> select * from t1;
ID START_TIME END_TIME
---------- ------------------- -------------------
1 07/15/2011 12:00:00 07/15/2011 12:00:05
1 07/15/2011 12:00:02 07/15/2011 12:00:04
1 07/15/2011 12:00:03 07/15/2011 12:00:06
1 07/15/2011 12:00:15 07/15/2011 12:00:20
这部分为您提供 7 月 15 日所有时间(直到秒)的列表...
select trunc(sysdate) + level/(24*60*60) time1
from dual
connect by level <= (trunc(sysdate)-trunc(sysdate-1))*24*60*60
将它加入主表,你会得到这个......(进程运行的每一分钟......)
SQL > break on id on start_time on end_time
select t1.id,
t1.start_time,
t1.end_time,
all_seconds.time1
from t1,
(select trunc(sysdate) + level/(24*60*60) time1
from dual
connect by level <= (trunc(sysdate)-trunc(sysdate-1))*24*60*60
) all_seconds
where all_seconds.time1 > t1.start_time
and all_seconds.time1 <= t1.end_time
ID START_TIME END_TIME TIME1
---------- ------------------- ------------------- -------------------
1 07/15/2011 12:00:00 07/15/2011 12:00:05 07/15/2011 12:00:01
07/15/2011 12:00:02
07/15/2011 12:00:03
07/15/2011 12:00:04
07/15/2011 12:00:05
2 07/15/2011 12:00:02 07/15/2011 12:00:04 07/15/2011 12:00:03
07/15/2011 12:00:04
3 07/15/2011 12:00:03 07/15/2011 12:00:06 07/15/2011 12:00:04
07/15/2011 12:00:05
07/15/2011 12:00:06
4 07/15/2011 12:00:15 07/15/2011 12:00:20 07/15/2011 12:00:16
07/15/2011 12:00:17
07/15/2011 12:00:18
07/15/2011 12:00:19
07/15/2011 12:00:20
从这里开始...您所需要的只是分钟的不同计数。如果您有另一列作为分组依据,则需要在末尾修改此查询。 (例如...项目、开始日期和结束日期...您想要总工作日...,您需要按 project_id (??) 分组)
select count(distinct(time1)) total_minutes
from (
select t1.id,
t1.start_time,
t1.end_time,
all_seconds.time1
from t1,
(select trunc(sysdate) + level/(24*60*60) time1
from dual
connect by level <= (trunc(sysdate)-trunc(sysdate-1))*24*60*60
) all_seconds
where all_seconds.time1 > t1.start_time
and all_seconds.time1 <= t1.end_time
)
/
TOTAL_MINUTES
-------------
11
此解决方案的问题在于它(或多或少)是暴力破解。 您必须生成所有可能时间的列表(如果您的数据跨越多个日期并且需要秒级精度处理时间,则生成的数据将非常庞大)。根据实际表的大小,连接可能性能不佳。
我仍在尝试看看是否可以通过分析优雅地解决这个问题。如果我想出更好的解决方案,会在此处发布。
关于多线程 - 查询以显示处理一组进程所用的总时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6712256/