从内存而不是表中获取数据
Posted
技术标签:
【中文标题】从内存而不是表中获取数据【英文标题】:getting data from memory instead of table 【发布时间】:2013-03-04 20:21:50 【问题描述】:我有一个 10 行的参数表。称为参数表。 在我的 PL/SQL 过程中,我循环了 200 万条记录。并且每次也查询这个参数表。
我想把这个参数表加载到内存中,减少I/O进程。
最好的方法是什么?
FOR cur_opt
IN (SELECT customer_ID,
NVL (customer_type, 'C') cus_type
FROM invoice_codes
WHERE ms.invoice_type='RT')
LOOP
....
...
Select data From parameter_table Where cus_type = cur_opt.cus_type AND cr_date < sysdate ; -- Where clause is much complex than this..
....
...
END LOOP;
【问题讨论】:
如果 Oracle 不将整个参数表保存到缓冲区缓存中,我会感到非常惊讶。我认为您试图解决一个不存在的问题(至少不是由于 10 行参数表)。 【参考方案1】:你可以把它加入你的主查询:
select customer_id, data
from parameter_table t, invoice_codes c
where t.cus_type = nvl(c.customer_type, 'C')
and t.cr_date < sysdate
但是,如果您在 invoice_codes
中有 200 万条记录,那么加入参数表是您最不关心的问题 - 循环执行此操作需要一些时间(这可能是您的 I/O 的真正原因问题)。
【讨论】:
赞成,因为这显然是最简单的事情,我没有引起足够的重视。但是,请使用 ANSI 连接。 对不起,因为节目流程,我无法加入。 如果您对您可以做什么有其他限制,请使用所有相关详细信息更新您的问题。但是,我不确定将其加入会如何影响程序流程。 因为select查询上面的where子句中的变量之间存在依赖关系。问题被编辑 磁盘 I/O 到参数表不是问题的根源。 10 行适合单个页面,可以很容易地保存在缓冲区缓存中。单个查询连续执行 200 万次会产生更大的开销。加入是解决方案。这也将修复可能的幻读。【参考方案2】:我认为您可以更改查询,加入参数表,因此无需在循环内点击 select 语句。 (就像@Chris Saxon 的解决方案一样)
但作为使用兑现数据的一种方式, 您可以填写一个像数组这样的字典,然后在必要时引用它 这样的事情可能会有所帮助:
你必须在启动主进程之前调用Fill_parameters_cash
并调用get_parameter
来获取数据,调用get_parameter
的输入参数是字典键
TYPE ga_parameter_t IS TABLE OF parameter_table%ROWTYPE INDEX BY BINARY_INTEGER;
ga_parameter ga_parameter_t;
procedure Fill_parameters_cash is
begin
ga_parameter.DELETE;
SELECT * BULK COLLECT
INTO ga_parameter
FROM parameter_table;
end Fill_parameters_cash;
FUNCTION get_parameter(cus_type invoice_codes.cus_type%TYPE,
is_fdound OUT BOOLEAN)
RETURN parameter_table%ROWTYPE IS
result_value parameter_table%ROWTYPE;
pos NUMBER;
BEGIN
result_value := NULL;
is_fdound := FALSE;
IF cus_type IS NULL THEN
RETURN NULL;
END IF;
pos := ga_parameter.FIRST;
WHILE pos IS NOT NULL
LOOP
EXIT WHEN ga_parameter(pos).cus_type = cus_type;
pos := ga_parameter.NEXT(pos);
END LOOP;
IF pos IS NOT NULL THEN
is_fdound := TRUE;
result_value := ga_parameter(pos);
END IF;
RETURN result_value;
END get_parameter;
【讨论】:
【参考方案3】:我猜循环遍历一百万条记录已经引起了问题。不太清楚这个参数表查找如何真正恶化它。
无论如何,如果这确实是您可以采用的唯一方法,那么您可以在游标声明中进行内部或外部联接。
----
FOR cur_opt
IN (SELECT customer_ID,
NVL (customer_type, 'C') cus_type
FROM invoice_codes codes,
parameter_table par
WHERE ms.invoice_type='RT'
and codes.cus_type = par.cus_type -- (or an outer join) maybe?
) loop
..........
【讨论】:
以上是关于从内存而不是表中获取数据的主要内容,如果未能解决你的问题,请参考以下文章
使用存储过程从视图中检索或过滤数据是不是比使用存储过程从表中获取或过滤数据更快?
选择一种方法而不是另一种方法从 Mysql 获取数据的复杂性