多线程 - 查询以显示处理一组进程所用的总时间

标签 multithreading algorithm oracle plsql

我正在尝试确定完成多线程应用程序的一组进程所花费的总时间,该多线程应用程序在表中跟踪开始和结束时间。描述我的问题的最简单方法是举个例子。

这是我正在使用的表格的精简版(我们称之为进程):

| 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/

相关文章:

oracle - PL/SQL ORA-01422 : exact fetch returns more than requested number of rows

python - 优雅地停止线程

algorithm - 我需要帮助实现一种算法,该算法将从 libGDX 中的纹理解析特定纹理

algorithm - 将 A* 搜索实现为广度优先搜索/深度优先搜索

python - 在非常具体的约束下生成随机数

database - 是否可以在 Oracle 11g express on virtualbox 上使用 "impdb"?

java - 如何将 Java Web 应用程序中的文件存储在 oracle 目录(而不是表)中

c# - 即使使用多线程,用户界面仍然锁定

Java:多线程

java - 我应该关心 Lollipop 及以后的主线程和 UI 线程之间的区别吗?