Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
![]() |
![]() |
Home -> Community -> Usenet -> c.d.o.server -> HELP -- Insert's Take Forever! (code attached)
Hi.
HELP! I'm working with a PL/SQL program that combines or consolidates orders from a database. My problem is that the inserts are SLOW AS DEATH!
I've attached the code, but I've had to "mask" it and simplify it in order to post it, so there may be some syntactical "bugs". Still the framework and all the elements are the same. In the code, I've identified THREE potential problem inserts and what they do. (I believe No. 2 is the culprit, but I'm not sure.) I've tried these with and without the append hint. No difference. I wonder, since the query in my cursor is kind of slow, if it's not running the query each time through the loop. It's not a speedy query. Really, I'm not sure where the bottleneck lies, but it takes about 30 seconds to process each iteration.
If someone has some general advice, or more detailed hints for me from looking at the code, I'd be grateful. Thanks in advance. (And please let me know if I've left anything out.)
-jk
PRELIMINARIES
This is an order invoicing application database. Orders have multiple line
items, line items have one or more "charges" associated with them. The table
names should be obvious. Orders typically have 10 to 20 line items (though
this varies greatly), and line_items typically have just one "charge". The
orders and line_items tables are large; upwards of 50,000 orders and maybe
300,000 line_items. This is an Oracle 8i database running in serial mode. No
statistics are kept.
WHAT THE PROGRAM DOES
All open orders for customers must be combined into a single new order. This
new order has all the same line items from the original orders. Each day the
program looks to see what customers are scheduled to have their orders
combined that day and then builds a single new CONSOLIDATED order from all
of that customer's open orders. The sum of the line items from the original
order should equal the number of line items on the new order (excluding
"deleted" lines; status = -99). The original orders are then closed.
HOW IT DOES IT
Orders and customers are brought back in the c_headers cursor, ordered by
customer. The cursor iterates through each order and when it detects a new
customer ID, a new order header is built. During each iteration, line items
for the current order are added under the new order header. Charges
associated with the line item are "copied over".
CREATE OR REPLACE PROCEDURE CONSOLIDATE(
p_region IN VARCHAR2(8)
) IS
v_customer_id NUMBER := 0; v_consolidated_no VARCHAR2(8); v_consolidated_id NUMBER; v_last VARCHAR2(9); v_pad VARCHAR2(1); v_size NUMBER v_lines NUMBER; v_shipped NUMBER; v_id NUMBER; v_is_new BOOLEAN; v_line_no_offset NUMBER := 0; v_row_count NUMBER := 0; v_has_lines BOOLEAN := FALSE;
CURSOR c_get_order_no(p IN VARCHAR2) IS
SELECT x, y, z
FROM t
WHERE a = 'A'
AND b = p
AND c = 0
FOR UPDATE;
CURSOR c_all_orders(p_region IN varchar2, p_date IN date) IS
BEGIN FOR r_header IN c_all_orders(p_region, SYSDATE) LOOP
v_is_new := (v_customer_id != r_header.customer_id);
IF v_is_new THEN
IF NOT v_has_lines THEN
ROLLBACK; --b/c we created a combined order with no detail lines; this
will revert the order
ELSE
COMMIT; --commit all others
END IF;
v_line_no_offset := 0;
v_has_lines := FALSE;
END IF;
v_customer_id := r_header.customer_id;
v_id := r_header.id;
IF v_is_new THEN
--new id of consolidated order/new order no v_consolidated_id := my_function('get_new_id'); OPEN c_get_order_no(r_header.region); FETCH c_get_order_no INTO v_last, v_pad, v_size;
UPDATE system_table_1 SET a = a + 1, b = b + 1 WHERE CURRENT OF c_get_order_no;
v_row_count := SQL%RowCount;
v_line_no_offset := v_line_no_offset + v_row_count;
IF v_row_count > 0 THEN
v_has_lines := TRUE;
COMMIT; --needed to enable the following query since it selects from the
rows inserted into the line items table above
INSERT INTO log_table (
id, type, consolidated_id, date ) VALUES ( v_id, 'T3', v_consolidated_id, SYSDATE
UPDATE line_item_table
SET status = 99,
changed_by = 'user99', change_date = SYSDATE
UPDATE orders_table
SET status = 99,
changed_by = 'user99', change_date = SYSDATE
![]() |
![]() |