If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

 
Go Back  dBforums > Database Server Software > DB2 > "MOVE rows procedure" (insert + delete)

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 01-10-06, 09:46
antti antti is offline
Registered User
 
Join Date: May 2004
Posts: 11
"MOVE rows procedure" (insert + delete)

Hi,

We are in need to implement SQL stored procedure to archive application data rows from "active" table to "archive" table after some period of days. The rows in active table can be somewhat large (they have CLOB fields, data size from 30 - 100 k.) and there usually is about 300 000 - 500 000 new rows per day in active table.

Because of the number of rows and data size, the transactions are long and fill the transaction logs quickly, these haven't been able to be moved in single huge transaction to archive table.

For this we have made quite simple SQL procedure, which moves the rows by making insert & deletes for 5000 rows in loop and commits, and then repeats until all rows are "moved" to archive table.

This SQL procedure has been running fine so far in development environment, but is this design infact faulty of how it selects which rows to delete after inserts (check the sample code) ? The insert and delete makes same query to same table, but is the data that the query returns always in same order between insert and delete executions ?! (are the deleted rows always, in all situations the same that were inserted ?)


The more I think the more this current design feels faulty Do you have some recommendations or tips what better options there would be for implementing this "move procedure" ? (using temp table ?)

Using ORDER BY for selects would ensure the order, but I wonder how big performance hit it might cause on bigger data volumes ... ?


Insert + delete part of the SQL procedure:
--------------------------------------------
-- prmNumberOfDays is input DATE parameter to procedure
SET archiveDate = (CURRENT_DATE - prmNumberOfDays DAYS);
SET countOfRowsToMove = (select count(*) from APP_ACTIVE where DATE(CREATED_TIMESTAMP) < archiveDate)

WHILE (countOfRowsToMove > 0) DO

-- Insert 5000 rows
insert into APP_ARCHIVE(APP_TIMESTAMP, WORK_ID, APP_DATA, CREATED_TIMESTAMP) (select APP_TIMESTAMP, WORK_ID, APP_DATA, CREATED_TIMESTAMP from APP_ACTIVE where DATE(CREATED_TIMESTAMP) < archiveDate FETCH FIRST 5000 ROWS ONLY);

-- Delete 5000 rows (are these always same rows than were in insert step ?)
delete from APP_ACTIVE where ID_APP_ACTIVE in (select ID_APP_ACTIVE from APP_ACTIVE where DATE(CREATED_TIMESTAMP) < archiveDate FETCH FIRST 5000 ROWS ONLY);

-- Commit change
COMMIT;

set countOfRowsToMove = countOfRowsToMove - 5000;

END WHILE;

--------------------------------------------

Thanks for your help.
Reply With Quote
  #2 (permalink)  
Old 01-10-06, 10:11
Cougar8000 Cougar8000 is offline
Registered User
 
Join Date: Nov 2005
Location: IL
Posts: 554
How about you use export to export the data to the temp file. Then use load to put a data into your archive table. This will speed the load process. Add commit statement to load statement. Let that finish. Add a check for the return code to make sure that it finished ok. Then you can safely delete from the original table. No need for fetch.

This will also assures that you infact moved all of the data before deletion takes place. And using a COMMITCOUNT as a part of the load will prevent you from filling up logs.
__________________
--
IBM Certified DBA on DB2 for Linux, UNIX, and Windows

DB2 v9.1.0.2 os 5.3.0.0
Reply With Quote
  #3 (permalink)  
Old 01-10-06, 10:24
ARWinner ARWinner is offline
Registered User
 
Join Date: Jan 2003
Posts: 3,575
Yes, I would say that your logic is faulty. There is no way to insure that the first 5000 rows in the subselect of the insert statement are the same first 5000 rows in the delete statement.

Probably a better way would be like this. (I am not 100% sure of the syntax).

DECLARE moredata int;
DECLARE commit_counter int;
declare cursor1 cursor with hold for select * from APP_ACTIVE where DATE(CREATED_TIMESTAMP) < archiveDate;

declare continue condition for not found set moredata = 0;

set moredata = 1;
set commit_counter = 0;
open cursor1;
fetch cursor1 into ....
while (moredata = 1) do
insert into ...
delete from APP_ACTIVE where current of cursor1;
set commit_count = commit_count + 1;
if (commit_count = 5000)
THEN
commit;
set_commit_count = 0;
END IF;
END WHILE;
COMMIT;


HTH

Andy
Reply With Quote
  #4 (permalink)  
Old 01-10-06, 12:50
juliane26 juliane26 is offline
Registered User
 
Join Date: Oct 2005
Posts: 109
The idea I have:
How about first load with a cursor to avoid the export?
logging is avoided then for the load, the deletion can take place in any order, no worrys.

From what I see you have no issue regarding that this takes too long. otherwise load and even export with following load on the base table when a huge percentage is deleted is an option.
__________________
Juliane
Reply With Quote
  #5 (permalink)  
Old 01-10-06, 13:24
Cougar8000 Cougar8000 is offline
Registered User
 
Join Date: Nov 2005
Location: IL
Posts: 554
with 300 - 500 thousand rows per day. he got to have issue with how long it takes if he is using an insert.
__________________
--
IBM Certified DBA on DB2 for Linux, UNIX, and Windows

DB2 v9.1.0.2 os 5.3.0.0
Reply With Quote
  #6 (permalink)  
Old 01-11-06, 03:48
juliane26 juliane26 is offline
Registered User
 
Join Date: Oct 2005
Posts: 109
Quote:
Originally Posted by Cougar8000
with 300 - 500 thousand rows per day. he got to have issue with how long it takes if he is using an insert.
:-) no further comment
__________________
Juliane
Reply With Quote
  #7 (permalink)  
Old 01-11-06, 08:42
antti antti is offline
Registered User
 
Join Date: May 2004
Posts: 11
Andy, thanks for your suggestion it seems prudent, we will try that. Thanks especially for pseudo code, it always clarifies things

About the export/load batch option ... otherwise yes that would be good option, but there is requirement that I didn't mention in first post, when the archiving will be started (not fixed date/time) should be able to be determined from (java) application (there is some app. specific processing before & after archive job, of course the application could start the export/load batch also ...). But as Cougar8000 there warned, export/load option might be for performance reason thing to consider anyway ...

Thanks for all your comments!
Reply With Quote
  #8 (permalink)  
Old 01-12-06, 03:39
gardenman gardenman is offline
Registered User
 
Join Date: Apr 2004
Posts: 54
Do like this:
-- the table from we will move data
create table t_from (
id int,
name char(30)
)@

-- the table to we will move data
create table t_to (
id int,
name char(30)
)@

-- insert sample data
insert into t_from values
(1,'aaaaa'),
(2,'bbbbb')
@

-- check what we have
select * from t_from@
select * from t_to@

----------------------------------------------------
-- the next statement moves rows from t_from to t_to
-- it uses select from delete
-- and select from insert
-- and returns number of moved rows
----------------------------------------------------
with
tf as (select * from old table (delete from t_from where id between 1 and 5000)),
tt as (select id,name from new table (insert into t_to (id,name) select id,name from tf))
select count(*) from tt
@

-- check what happen?
select * from t_from@
select * from t_to@

-- change to commit if everything is ok!
rollback@
Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On