我正在尝试调整用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循环(这是程序的最后一步)循环次数过多导致程序运行时间过长。我想知道是否有办法将CAST
主机结构数组ps_errors
添加到Oracle表类型中,以便我可以轻松地批量UPDATE
或甚至执行MERGE
一些并行的DML,无需遍历每条记录。
答案 0 :(得分:0)
从我在工作中看到的其他一些类似的代码推断,你可以做这样的事情而不是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
的内容被空终止。鉴于在现有代码中使用strcpy()
而不是strncpy()
(或类似),我猜测它们已经存在。
如果s_err_msg
可以为null,您还应该考虑使用indicator variables。例如
error_message = :ps_errors.s_err_msg INDICATOR :indicator_variable
答案 1 :(得分:0)
您可以使用数组更新http://docs.oracle.com/cd/B28359_01/appdev.111/b28427/pc_08arr.htm#i1879但是您需要将结构数组ps_errors
更改为数组结构
E.g:
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;