2015-01-16 29 views
-1

我有一個表名tbl_tmp_trans 它包含了每一個用戶的交易做過(和它現在是給6Mil!)保持每個用戶最後100成交,並刪除其餘

我們決定只保留最近100交易每個用戶在我們的數據庫中,以便我們能保持清潔分貝這裏 的是,我有

delete from tbl_tmp_trans 
where trans_id in 
(
    select trans_id 
    from 
    (
     select trans_id 
     from tbl_faucets_transactions 
     order by date 
     group by user_id 
     limit 100 
    ) foo 
) 

我在做什麼錯想出了一個查詢?

因爲這樣做後,我的CPU達到100%,MySQL崩潰。

在此先感謝 PS:我們的db是MySQL和臺發動機是Innodb的

P.S2:我們有大約120K和transction表有6附近萬人次的紀錄

+0

不知道您的系統中有多少用戶,但您可能想要接受此查詢併爲其添加另一個參數(userid),因此您並不試圖一次性運行整個數據庫。 – user2366842

+0

@ user2366842我們有約120k用戶 – far2005

+0

請顯示EXPLAIN結果。 –

回答

0

我有一個提議...希望它可以幫助你。

改變你的表:

alter table tbl_tmp_trans add column todel tinyint(1); 

實現一個存儲過程通過表遊標和標記迭代(設置todel1)應該被刪除的記錄。實例程序要做到這一點:

delimiter // 
drop procedure if exists mark_old_transactions // 
create procedure mark_old_transactions() 
begin 
    declare done int default false; 
    declare tid int; 
    declare uid int; 
    declare last_uid int default 0; 
    declare count int default 0; 
    declare cur cursor for select trans_id, user_id from tbl_tmp_trans order by user_id, date desc; 
    declare continue handler for not found set done = true; 

    open cur; 
    repeat 
     fetch cur into tid, uid; 
     if (!done) then 
      if (uid!=last_uid) then 
       set count = 0; 
      end if; 
      set last_uid = uid; 
      set count = count + 1; 
      if (count > 100) then 
       update tbl_tmp_trans set todel=1 where trans_id=tid; 
      end if; 
     end if; 
    until done 
    end repeat; 
    close cur; 
end // 

調用程序,也許做一些簡單的檢查(你從表中有多少事務刪除等),並刪除標記的記錄。

call mark_old_transactions; 
-- select count(*) from tbl_tmp_trans where todel=1; 
-- select count(*) from tbl_tmp_trans; 
delete from tbl_tmp_trans where todel=1; 

最後,刪除我們剛剛添加的列。

alter table tbl_tmp_trans drop column todel; 

一些注意事項:

  • 也許你必須通過表 的所有記錄進行迭代,所以你不要用光標鬆動的表現。
  • 如果您擁有約120K個用戶和約6M個交易,則平均每個用戶約有50個交易。這意味着,可能你並不真的 有超過100個交易的用戶太多,所以 更新(希望)的數量不會太多。 =>程序運行速度相對較快。
  • 刪除應該快速與新列。
相關問題