MySQL NDB 批量更新100萬行資料

feelpurple發表於2016-08-05
生產NDB資料庫中的一張800多萬行的大表需要更新部分欄位,為減少對資料庫效能的影響,編寫了一個儲存過程來實現:
1. 匯出這張表的主鍵欄位,資料量有100多萬條
select MSISDN from TEST where LastAccessTimeStamp=0
into outfile '/tmp/TEST_out.txt' fields terminated by ',' ;

2. 在其中一個SQL節點,建立兩張臨時表
--建立第一張臨時表,用於和生產資料庫的源表主鍵進行關聯,以更新部分欄位
create table tmp_Subscribers_01(id int not null auto_increment primary key,MSISDN char(20)) engine=innodb;
--向第一張臨時表匯入之前的匯出資料
load data infile '/tmp/Subscribers_out.txt' into table tmp_Subscribers_01 fields terminated by ',' (MSISDN);
--建立第二張臨時表,用於記錄資料更新的進度
create table tmp_Subscribers_02(id int, MSISDN char(20),cdate datetime) engine=innodb;

3. 編寫資料更新的儲存過程
drop procedure proc_Subscribers_update;
delimiter $$
create procedure proc_Subscribers_update(IN v_fetch_cnt INT, IN v_sleep_secs INT)
begin
DECLARE v_count INT;
DECLARE v_times INT DEFAULT 1;
DECLARE v_max_value INT;
  /*compute the times that the loop runs*/
  select ceil(count(MSISDN)/v_fetch_cnt) into v_count from tmp_Subscribers_01;
  /*compute the maximum rows that have been already updated*/
  WHILE v_times < v_count DO
    select ifnull(max(id),0) into v_max_value from tmp_Subscribers_02;
    if v_max_value < v_fetch_cnt * v_count then
      SET v_times = 1 + floor(v_max_value/v_fetch_cnt);
      update TEST s,tmp_Subscribers_01 t set s.LastAccessTimeStamp=1420066800
      where s.MSISDN=t.MSISDN and t.id > v_max_value and t.id <= v_fetch_cnt * v_times;
      /*record the processing rows*/
      insert into tmp_Subscribers_02 select id, MSISDN, now() from tmp_Subscribers_01 where id = v_fetch_cnt * v_times;
      select concat('The job',' has already updated ', v_fetch_cnt * v_times, ' rows..') as Info;
      select sleep(v_sleep_secs);
    end if;
    commit;
  END WHILE;
  select concat('The job',' is ','finished!') as Info;
  commit;
end$$
delimiter ;

--執行儲存過程
--其中第一個傳入引數為每次更新的行數,第二個引數為每次更新後的休眠時間
call proc_Subscribers_update(10000, 2);

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26506993/viewspace-2123040/,如需轉載,請註明出處,否則將追究法律責任。

相關文章