【解決方案】mysql大數據刪除


背景:生產環境,單表數據量在400W條,數據占空間約20G,無索引。
數據庫引擎使用的是InnoDB,InnoDB數據庫對於已經刪除的數據只是標記為刪除,並不真正釋放所占用的磁盤空間,所以InnoDB數據庫文件會不斷增長。

目標是根據創建時間,僅保留近一個月的記錄,最簡朴的sql語句如下:

DELETE FROM log_interface WHERE datediff(SYSDATE(), createdon) > 30;


根據執行計划查詢預計需要刪除300W條,所刪數據占空間約15G,根據以往經驗,直接用上述sql進行數據刪除需要超過十分鍾,影響過大。
1. 如果是要刪除整個表,使用命令 truncate table 效率最高;
2. 如果需要刪除的數據量沒有這么大,可以分多次刪除,每次操作使用 limit 限制刪除條數:

DELETE FROM log_interface WHERE datediff(SYSDATE(), createdon) > 30 limit 10000; -- 刪除一次數據大概需要10s


3. 以上操作都不適應我們當前的場景,我們需要刪除的數據超過表數據的50%,建議拷貝所需數據到臨時表,然后重命名原表為其他名字,重命名臨時表為原表名稱,具體sql如下:

CREATE TABLE `log_interface_bak` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
`trance_id` varchar(64) DEFAULT NULL COMMENT '一條請求鏈路(Trace)的唯一標識',
`span_id` varchar(64) DEFAULT NULL COMMENT '一個工作單元(Span)的唯一標識,必須值',
`parent_span_id` varchar(64) DEFAULT NULL COMMENT '標識當前工作單元所屬的上一個工作單元,Root Span(請求鏈路的第一個工作單元)的該值為空',
`hospital_name` varchar(64) DEFAULT NULL COMMENT '所屬醫院名稱',
`hospital_id` varchar(64) DEFAULT NULL COMMENT '所屬醫院ID',
`factory_id` int(11) DEFAULT NULL COMMENT '廠商id',
`docking_id` int(11) DEFAULT NULL COMMENT '對接類型id',
`basic_interface_info_id` int(11) DEFAULT NULL COMMENT '標准接口id',
`interface_name` varchar(64) DEFAULT NULL COMMENT '接口名稱',
`business_id` int(11) DEFAULT NULL COMMENT '業務標簽',
`interface_call_time` datetime(3) DEFAULT NULL COMMENT '接口調用時間',
`interface_response_time` bigint(20) DEFAULT NULL COMMENT '接口響應時間',
`interface_response_state` tinyint(1) DEFAULT NULL COMMENT '接口響應狀態 0 失敗 1 成功',
`interface_fail_reason` varchar(1024) DEFAULT NULL COMMENT '接口調用失敗原因',
`input_param` text COMMENT '接口入參',
`output_param` text COMMENT '接口出參',
`remarks` varchar(1024) DEFAULT NULL COMMENT '備注',
`deletion_state` char(1) DEFAULT '0' COMMENT '刪除狀態,0未刪除,1已刪除',
`createdon` datetime(3) DEFAULT NULL COMMENT '創建時間',
`createdby` varchar(64) DEFAULT NULL COMMENT '創建者',
`modifiedon` datetime DEFAULT NULL COMMENT '修改時間',
`modifiedby` varchar(64) DEFAULT NULL COMMENT '修改者',
`is_basic_type` tinyint(1) DEFAULT NULL COMMENT '是否標准接口 0 否 1 是',
`path` varchar(128) DEFAULT NULL COMMENT '請求地址',
`flow` bigint(20) DEFAULT NULL COMMENT '數據流量',
`business_log_tag` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11456328 DEFAULT CHARSET=utf8 COMMENT='接口日志(標准接口,醫院接口)記錄表';

將 log_interface 表中需要留存的數據備份到 log_interface_bak 表:

insert into log_interface_bak SELECT * FROM log_interface WHERE datediff( SYSDATE( ), createdon ) < 30; -- 耗時196.427s

對表進行重命名:

RENAME TABLE log_interface to log_interface_a , log_interface_old to log_interface; -- 耗時0.238s

最后刪除log_interface_a表。

參考文檔:http://mysql.rjweb.org/doc.php/deletebig


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM