我正在尝试调整一段用Pro*C编写的大型代码,特别是瓶颈循环和其中的UPDATE
语句。for loop
遍历"主机结构数组",该数组可能包含数千条有时数百万条记录,并且更新执行的次数过多。更新可以在整个程序中更频繁地执行,但这需要对代码进行重大更改,我没有进行重大更改的自由。
所以我有这样的东西
....
#define NULL_REF_NO 10
#define NULL_ERR 256
....
....
struct s_errors
{
char s_ref_id [NULL_REF_NO];
char s_ref_seq_no [NULL_REF_NO];
char s_err_msg [NULL_ERR];
};
....
....
struct s_errors *ps_errors = NULL;
....
....
/*The part below happens throughout the program to collect all errors*/
/*ls_ref_id, ls_ref_seq_no, and ls_err_msg are local variables of same data type. and i_curr_index is the array index variable*/
strcpy(ls_ref_id, ps_errors[i_curr_index].s_ref_id);
strcpy(ls_ref_seq_no, ps_errors[i_curr_index].s_ref_seq_no);
strcpy(ls_err_msg, ps_errors[i_curr_index].s_err_msg);
.....
/* At this point ps_error contains thousands or even millions of rows*/
/* The final part is to update all these rows back to the table like below*/
/* pl_err_count is a Global var which keeps track of the total number of records in the host structure array*/
int i_curr_index = 0;
char l_ref_id [NULL_REF_NO];
char l_ref_seq_no [NULL_REF_NO];
char l_err_msg [NULL_ERR];
for(i_curr_index = 0; i_curr_index < pl_err_count; i_curr_index++)
{
strcpy(l_ref_id, ps_errors[i_curr_index].s_ref_id);
strcpy(l_ref_seq_no, ps_errors[i_curr_index].s_ref_seq_no);
strcpy(l_err_msg, ps_errors[i_curr_index].s_err_msg);
EXEC SQL
UPDATE some_table
SET status = 'E',
error_message = :l_err_msg
WHERE ref_id = :l_ref_id
AND ref_seq_no = :l_ref_seq_no;
if (SQL_ERROR_FOUND)
{
sprintf(err_data, "Updation failed with sql errors ");
strcpy(table, "some_table");
WRITE_ERROR(SQLCODE,function,"",err_data);
return(FATAL);
}
}
瓶颈是上面的 for 循环(这是程序的最后一步),它循环太多次导致程序运行很长时间。我想知道是否有办法将主机结构数组ps_errors
CAST
为 Oracle 表类型,以便我可以轻松地进行批量UPDATE
,甚至使用一些并行 DML 进行MERGE
,而无需遍历每条记录。
从我在工作中看到的其他一些代码推断,你可以做这样的事情而不是for
循环:
EXEC SQL for :pl_err_count
UPDATE some_table
SET status = 'E',
error_message = :ps_errors.s_err_msg
WHERE ref_id = :ps_errors.s_ref_id
AND ref_seq_no = :ps_errors.s_ref_seq_no;
这可能依赖于添加到 ps_errors
null 终止的内容。鉴于在现有代码中使用了strcpy()
而不是strncpy()
(或类似),我猜它们已经使用了。
如果s_err_msg
可以为 null,则还应考虑使用指示符变量。
error_message = :ps_errors.s_err_msg INDICATOR :indicator_variable
<</div>
div class="one_answers">您可以使用数组更新 http://docs.oracle.com/cd/B28359_01/appdev.111/b28427/pc_08arr.htm#i1879 但您需要将结构数组更改为数组的结构ps_errors
例如:
EXEC SQL
UPDATE some_table
SET status = 'E',
error_message = :ps_errors.s_err_msg
WHERE ref_id = :ps_errors.s_ref_id
AND ref_seq_no = :ps_errors.s_ref_seq_no;