【问题标题】:Analysing large data set in Oracle Database do it in Memory or Iterative Query?分析 Oracle 数据库中的大型数据集是在内存还是迭代查询中进行?
【发布时间】:2013-09-24 17:17:05
【问题描述】:

全部,

请注意,为简单起见,我在下面创建了以下场景来帮助解决这个问题,这与我遇到的实际问题非常接近。

有一个名为“State”的表,出于所有意图和目的,该表包含一个与另一个名为“Stock”的表相关的值,该表包含有关对象的数据。

例如

+-----+-------+
|TABLE| VALUE |
+-----+-------+
|Stock| Ball  |
+-----+-------+
|State|Instock|
+-----+-------+

所以从上面的例子来看,根据 State 表,Stock 表中名为“Ball”的记录是“Instock”。

但是要得出这个结论,我需要分析另一个名为 Items 的表,它是现实世界中该库存中存在多少物理项目的真实值所以如果有项目或没有项目可用,这将影响价值与该 Stock 记录相关的 State 表。

现在要分析并修改状态,我需要从 State 表开始,通过 Stock 表导航到 Items 表,如下所示

State ----> Stock ----> Items

现在这张表中有很多记录,至少每天都需要监控。

我以前从未从事过这样的事情,但是我的直觉告诉我,我可以获取所有表格并将它们作为数据对象加载到我的分析应用程序中,并在内存中虚拟地形成关系。

所以我需要做的就是在开始时执行一个大查询并将所有 SQL 结果加载到内存中。这是可能的还是明智的?

但是我考虑的另一个选项只是像这样遍历每个记录。按顺序执行许多事务。

State record 1 ----> Stock record 1 ----> Analyse Items records --> Update State record 1
State record 2 ----> Stock record 2 ----> Analyse Items records --> Updates State record 2
.......

这两种方法中的任何一种都是不错的选择吗?还是有其他方法可以做到这一点?

约束

  • Oracle 11g 数据库
  • 无法更改架构或表
  • 考虑将 JavaPerl 用于此分析应用程序
  • 此应用程序将是外部应用程序,并且与 DB 不在同一物理位置

伪代码

Get all state records in State table
Find their related records in Stock table
Find all child records of Stock table in Items table
Modify state of current record 
Move onto next record set.

因此,欢迎任何我可以用于解决此问题的指导或特定方法/功能。

请不要给我一个解决方案,我只要求朝正确的方向轻推一下 :)

【问题讨论】:

  • 所以澄清一下,你的最终目标是什么?用天气更新状态记录的最终目标是有库存吗?多久运行一次?
  • 另外,您能否估计一下每个表中有多少行。
  • 在我感兴趣的数据中,我将平均每天处理数百万行数的表中的 30,000 行。

标签: java sql oracle perl data-analysis


【解决方案1】:

我首先要说状态表是个坏主意。您已经根据项目的数量知道状态,因此当这种变化(经常)时,您的状态表有无效(过时的)条目。我还假设你不能改变这个结构,而只需要不断地保持这个状态。

我将作为单个更新语句运行(确保您有足够的回滚),但受影响的 30k 行并不是很大。例如:

> set serveroutput on
> drop table stock
table STOCK dropped.
> create table stock
(
stock_id number,
name varchar2(20)
)
table STOCK created.
> drop table item
table ITEM dropped.
> create table item
(
item_id number,
stock_id number,
num number
)
table ITEM created.
> drop table state
table STATE dropped.
> -- this really doesnt need to exist
> create table state
(
stock_id number,
val varchar2(20)
)
table STATE created.
> insert into stock values (1,'Ball')
1 rows inserted.
> insert into stock values (2,'Chair')
1 rows inserted.
> insert into stock values (3,'Pen')
1 rows inserted.
> insert into item (item_id, stock_id, num) values (1, 1, 35)
1 rows inserted.
> insert into item (item_id, stock_id, num) values (2, 2, 0)
1 rows inserted.
> insert into item (item_id, stock_id, num) values (3, 3, 1)
1 rows inserted.
> insert into state (stock_id, val) values (1, 'InStock')
1 rows inserted.
> insert into state (stock_id, val) values (2, 'OutOfStock')
1 rows inserted.
> insert into state (stock_id, val) values (3, 'InStock')
1 rows inserted.
> commit
committed.
> -- change number of items for Chairs
> update item set num=5 where stock_id = (select stock_id from stock where name = 'Chair')
1 rows updated.
> commit
committed.
> -- state is now wrong
> select st.name, i.num, s.val 
from stock st, state s, item i
where st.stock_id = i.stock_id
and st.stock_id = s.stock_id
NAME                        NUM VAL                
-------------------- ---------- --------------------
Ball                         35 InStock              
Chair                         5 OutOfStock           
Pen                           1 InStock              

> -- now we need to maintain "State" table
> update state st
set (st.val) = (
  select decode(i.num, 0, 'OutOfStock','InStock')
  from item i
  where i.stock_id = st.stock_id
)
-- only update those with invalid state values
where exists (
  select stock_id
  from item i
  where i.stock_id = st.stock_id
  and st.val <> decode(i.num, 0, 'OutOfStock','InStock')
)
1 rows updated.
> commit
committed.
> -- state is corrected
> select st.name, i.num, s.val 
from stock st, state s, item i
where st.stock_id = i.stock_id
and st.stock_id = s.stock_id
NAME                        NUM VAL                
-------------------- ---------- --------------------
Ball                         35 InStock              
Chair                         5 InStock              
Pen                           1 InStock    

【讨论】:

  • 感谢您的建议,但我无法更改它,它是一个名为 Siebel 的包的应用程序数据库。这就是表格的工作方式。
  • @loosebruce 我明白了。我的回答(请参阅上面的更新声明)应该对您有用,而无需更改您当前的架构。我只是评论说你必须维护的状态表不是一个好的设计方法。
【解决方案2】:

我的建议是编写一段 PL/SQL 代码,然后通过计划作业调用它。

调度程序文档: http://docs.oracle.com/cd/B28359_01/server.111/b28310/schedadmin006.htm

确实没有理由使用 Java 或 Perl 来处理这个问题,因为这只是不必要的连接,以及 oracle 环境之外的配置。只需记住要维护的另一个应用程序,而如果它在 Oracle 中,它将很容易访问和维护(但仍将其置于源代码控制中)。

至于实际的查询,这应该不会太难。您可以根据每个表中有多少行来进行简单的更新语句。类似的东西

UPDATE STATE SET STATE.INSTOCK = TRUE 
    WHERE STATE.PK IN (
        SELECT ITEMS.STATEFK FROM ITEMS WHERE ITEMS.COUNT > 0
    );

然后做同样的事情,但在 count

这对于 PL/SQL 来说根本不是正确的语法,但应该让您大致了解查询应该如何工作。

【讨论】:

  • 谢谢,我会调查的。我希望 DBAdmin 不会介意我弄乱他的服务器。
  • 那些讨厌的 DBAdmins,总是如此保护数据!询问他们是否有沙盒环境,或者可以创建一个沙盒环境,这样您就不会弄乱生产数据。此外,根据管理员的技能,他们可能会帮助您整理一些 PL/SQL。我总是对一些 DB 人员能够立即拼凑起来的疯狂东西感到惊讶。
猜你喜欢
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-09
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 2021-04-24
相关资源
最近更新 更多