首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Oracle:选择并行条目

Oracle:选择并行条目
EN

Stack Overflow用户
提问于 2015-03-19 15:29:58
回答 1查看 123关注 0票数 3

我正在搜索在一个相对较大的表中进行相对复杂查询的最有效方法。

这一概念是:

  • 我有一个表,它保存可以并行运行的各个阶段的记录。
  • 记录数量超过500万(并增加)
  • 这一时期大约5年前开始。
  • 由于性能原因,此选择可以在最后3个月的300.000条记录中应用(只有在物理上不可能对整个表执行)
  • 甲骨文版本: 11g

数据示例如下所示

代码语言:javascript
运行
复制
Table Phases (ID, START_TS, END_TS, PRIO)

1  10:00:00 10:20:10 10
2  10:05:00 10:10:00 11
3  10:05:20 10:15:00 9
4  10:16:00 10:25:00 8
5  10:24:00 10:45:15 1
6  10:26:00 10:30:00 10
7  10:27:00 10:35:00 15
8  10:34:00 10:50:00 5
9  10:50:00 10:55:00 20
10 10:55:00 11:00:00 15

上面您可以看到信息当前是如何存储的(当然,还有几个包含无关信息的其他列)。

有两个要求(或需要解决的问题)

  1. 如果我们对所有阶段的持续时间进行求和,则结果比上述数据所代表的时间要长得多。(各阶段之间可能存在漏洞,因此只使用第一个start_ts和最后一个end_ts是不够的)。
  2. 数据应该以如下所示的形式显示:哪个阶段与哪个阶段并行运行,哪个阶段每次具有最高优先级,如下面的预期的视图所示。

在这里,很容易区分每个时刻的最高优先级阶段(HIGHEST_PRIO),并且添加它们的持续时间将导致实际的总持续时间。

代码语言:javascript
运行
复制
View V_Parallel_Phases (ID, START_TS, END_TS, PRIO, HIGHEST_PRIO) 
-> Optional Columns: Part_of_ID / Runs_Parallel

1  10:00:00 10:05:20 10 True  (--> Part_1 / False)
1  10:05:20 10:15:00 10 False (--> Part_2 / True)
2  10:05:00 10:10:00 11 False (--> Part_1 / True)
3  10:05:20 10:15:00  9 True  (--> Part_1 / True)
1  10:15:00 10:16:00 10 True  (--> Part_3 / True)
1  10:16:00 10:20:10 10 False (--> Part_4 / True)
4  10:16:00 10:24:00  8 True  (--> Part_1 / True)
4  10:24:00 10:25:00  8 False (--> Part_2 / True)
5  10:24:00 10:45:15  1 True  (--> Part_1 / True)
6  10:26:00 10:30:00 10 False (--> Part_1 / True)
7  10:27:00 10:35:00 15 False (--> Part_1 / True)
8  10:34:00 10:45:15  5 False (--> Part_1 / True)
8  10:45:15 10:50:00  5 True  (--> Part_2 / True)
9  10:50:00 10:55:00 20 True  (--> Part_2 / False)
10 10:55:00 11:00:00 15 True  (--> Part_2 / False)

不幸的是,我不知道有一种有效的方法来进行这个查询。当前的解决方案是在生成大型报告的工具中以编程方式进行上述计算,但这是完全失败的。从计算前所需的30秒开始,现在需要超过10分钟,而不考虑各阶段的优先次序。

然后,我考虑将这段代码转换为sql中的任何一种: a)视图b)物化视图c)一个表,我会偶尔填充一个过程(取决于所需的持续时间)。

PS:我知道oracle有一些分析功能,可以处理复杂的查询,但我不知道这些功能实际上可以帮助我解决当前的问题。

提前谢谢你!

EN

回答 1

Stack Overflow用户

发布于 2015-03-22 20:48:49

这是一个不完整的答案,但在继续之前,我需要知道这种方法是否可行。我相信完全可以在SQL中完成,但我不确定性能如何。

首先,找出有过渡的所有时间点:

代码语言:javascript
运行
复制
CREATE VIEW Events AS
    SELECT START_TS AS TS
      FROM Phases
    UNION
    SELECT END_TS AS TS
      FROM Phases
;

然后从这些时间点创建(开始、结束)元组:

代码语言:javascript
运行
复制
CREATE VIEW Segments AS
     SELECT START.TS AS START_TS,
            MIN(END.TS) AS END_TS
      FROM Events AS START
      JOIN Events AS END
     WHERE START.TS < END.TS
;

从现在起,做剩下的事情应该是相当直接的。下面是一个查询,它列出了给定段中活动的段和所有阶段:

代码语言:javascript
运行
复制
  SELECT *
    FROM Segments
    JOIN Phases
   WHERE Segments.START_TS BETWEEN Phases.START_TS AND Phases.END_TS
     AND Segments.END_TS BETWEEN Phases.START_TS AND Phases.END_TS
ORDER BY Segments.START_TS
;

其余部分可以通过子选择和一些聚合来完成。

代码语言:javascript
运行
复制
| START_TS |   END_TS | ID | START_TS |  END_TS  | PRIO |
|----------|----------|----|----------|----------|------|
| 10:00:00 | 10:05:00 |  1 | 10:00:00 | 10:20:10 |   10 |
| 10:05:00 | 10:05:20 |  1 | 10:00:00 | 10:20:10 |   10 |
| 10:05:00 | 10:05:20 |  2 | 10:05:00 | 10:10:00 |   11 |
| 10:05:20 | 10:10:00 |  1 | 10:00:00 | 10:20:10 |   10 |
| 10:05:20 | 10:10:00 |  2 | 10:05:00 | 10:10:00 |   11 |
| 10:05:20 | 10:10:00 |  3 | 10:05:20 | 10:15:00 |    9 |
| 10:10:00 | 10:15:00 |  1 | 10:00:00 | 10:20:10 |   10 |
| 10:10:00 | 10:15:00 |  3 | 10:05:20 | 10:15:00 |    9 |
| 10:15:00 | 10:16:00 |  1 | 10:00:00 | 10:20:10 |   10 |
| 10:16:00 | 10:20:10 |  1 | 10:00:00 | 10:20:10 |   10 |
| 10:16:00 | 10:20:10 |  4 | 10:16:00 | 10:25:00 |    8 |
| 10:20:10 | 10:24:00 |  4 | 10:16:00 | 10:25:00 |    8 |
| 10:24:00 | 10:25:00 |  4 | 10:16:00 | 10:25:00 |    8 |
| 10:24:00 | 10:25:00 |  5 | 10:24:00 | 10:45:15 |    1 |
| 10:25:00 | 10:26:00 |  5 | 10:24:00 | 10:45:15 |    1 |
| 10:26:00 | 10:27:00 |  5 | 10:24:00 | 10:45:15 |    1 |
| 10:26:00 | 10:27:00 |  6 | 10:26:00 | 10:30:00 |   10 |
| 10:27:00 | 10:30:00 |  5 | 10:24:00 | 10:45:15 |    1 |
| 10:27:00 | 10:30:00 |  6 | 10:26:00 | 10:30:00 |   10 |
| 10:27:00 | 10:30:00 |  7 | 10:27:00 | 10:35:00 |   15 |
| 10:30:00 | 10:34:00 |  5 | 10:24:00 | 10:45:15 |    1 |
| 10:30:00 | 10:34:00 |  7 | 10:27:00 | 10:35:00 |   15 |
| 10:34:00 | 10:35:00 |  8 | 10:34:00 | 10:50:00 |    5 |
| 10:34:00 | 10:35:00 |  5 | 10:24:00 | 10:45:15 |    1 |
| 10:34:00 | 10:35:00 |  7 | 10:27:00 | 10:35:00 |   15 |
| 10:35:00 | 10:45:15 |  5 | 10:24:00 | 10:45:15 |    1 |
| 10:35:00 | 10:45:15 |  8 | 10:34:00 | 10:50:00 |    5 |
| 10:45:15 | 10:50:00 |  8 | 10:34:00 | 10:50:00 |    5 |
| 10:50:00 | 10:55:00 |  9 | 10:50:00 | 10:55:00 |   20 |
| 10:55:00 | 11:00:00 | 10 | 10:55:00 | 11:00:00 |   15 |

这里有一个SQL小提琴演示了整个过程:

http://sqlfiddle.com/#!9/d801b/2

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29148697

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档