У меня 40 миллионов записей в пользовательской таблице и на несколько миллионов меньше записей в соответствующей пользовательской таблице. Теперь я хочу заархивировать более старые записи более чем на 3 месяца в архивной таблице.
У меня есть хранимая процедура, которая переместить запись в новую таблицу и удалить из исходной таблицы. Если во время перемещения записи произошло какое-либо исключение из-за внешнего ключа, то ни одна запись не перемещалась. Также процедура занимает слишком много времени.
Пожалуйста, помогите мне в том же.
Исходные таблицы и архивная таблица и хранимая процедура, как показано ниже:
CREATE TABLE `user` (
`password` varchar(128) NOT NULL,
`last_login` datetime DEFAULT NULL,
`is_superuser` tinyint(1) NOT NULL,
`subscriber_id` bigint(20) NOT NULL,
`first_name` varchar(40) NOT NULL,
`middle_name` varchar(40) NOT NULL,
`last_name` varchar(40) NOT NULL,
`email` varchar(254) DEFAULT NULL,
`is_staff` tinyint(1) NOT NULL,
`is_active` tinyint(1) NOT NULL,
`date_joined` datetime NOT NULL,
`favorites` varchar(1024) NOT NULL,
`last_played` varchar(1024) NOT NULL,
`alias` varchar(32) NOT NULL,
PRIMARY KEY (`subscriber_id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `userprofile` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`profile_image` varchar(100) DEFAULT NULL,
`alias` varchar(40) DEFAULT NULL,
`dob` date DEFAULT NULL,
`created_at` datetime DEFAULT current_timestamp(),
`gender` varchar(1) DEFAULT NULL,
`age_group` varchar(100) DEFAULT NULL,
`location` varchar(300) DEFAULT NULL,
`updated_at` datetime DEFAULT current_timestamp(),
`subscriber_id` bigint(20) NOT NULL,
`state` varchar(100) DEFAULT NULL,
`city` varchar(100) DEFAULT NULL,
`email` varchar(254) DEFAULT NULL,
`dateOfBirth` datetime DEFAULT NULL,
`gamer_name` varchar(40) DEFAULT NULL,
`mobile_no` bigint(20) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=2009216 DEFAULT CHARSET=latin1;
CREATE TABLE `user_archived` (
`password` varchar(128) NOT NULL,
`last_login` datetime DEFAULT NULL,
`is_superuser` tinyint(1) NOT NULL,
`subscriber_id` bigint(20) NOT NULL,
`first_name` varchar(40) NOT NULL,
`middle_name` varchar(40) NOT NULL,
`last_name` varchar(40) NOT NULL,
`email` varchar(254) DEFAULT NULL,
`is_staff` tinyint(1) NOT NULL,
`is_active` tinyint(1) NOT NULL,
`date_joined` datetime NOT NULL,
`favorites` varchar(1024) NOT NULL,
`last_played` varchar(1024) NOT NULL,
`alias` varchar(32) NOT NULL,
`archive_dt` timestamp default CURRENT_TIMESTAMP,
PRIMARY KEY (`subscriber_id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `userprofile_archived` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`profile_image` varchar(100) DEFAULT NULL,
`alias` varchar(40) DEFAULT NULL,
`dob` date DEFAULT NULL,
`created_at` datetime DEFAULT current_timestamp(),
`gender` varchar(1) DEFAULT NULL,
`age_group` varchar(100) DEFAULT NULL,
`location` varchar(300) DEFAULT NULL,
`updated_at` datetime DEFAULT current_timestamp(),
`subscriber_id` bigint(20) NOT NULL,
`state` varchar(100) DEFAULT NULL,
`city` varchar(100) DEFAULT NULL,
`email` varchar(254) DEFAULT NULL,
`dateOfBirth` datetime DEFAULT NULL,
`gamer_name` varchar(40) DEFAULT NULL,
`mobile_no` bigint(20) unsigned DEFAULT NULL,
`archive_dt` timestamp DEFAULT now(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
DELIMITER $$
DROP PROCEDURE IF EXISTS `debug_msg`$$
DROP PROCEDURE IF EXISTS `insert_test_data`$$
DROP PROCEDURE IF EXISTS `delete_test_data`$$
DROP PROCEDURE IF EXISTS `UserArchive`$$
CREATE PROCEDURE debug_msg(enabled INTEGER, msg VARCHAR(255))
BEGIN
IF enabled THEN
select concat('** ', msg) AS '** DEBUG:';
END IF;
END$$
CREATE PROCEDURE insert_test_data(IN NUM int)
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE _NM varchar(25) default null;
DECLARE _ID bigint default 0;
DECLARE _PRO_ID bigint default 9215;
DECLARE _CDT timestamp;
DECLARE _DOB date default date('2000-03-23');
WHILE i < NUM DO
SELECT max(subscriber_id)+1 INTO _ID FROM user;
SELECT SUBSTRING(MD5(RAND()) FROM 1 FOR 8) INTO _NM;
SELECT from_unixtime(unix_timestamp('2017-10-01') + floor(rand() * (unix_timestamp('2018-06-30') - unix_timestamp('2017-06-01') + 1))) INTO _CDT;
INSERT INTO user (password,last_login,is_superuser,subscriber_id,first_name,middle_name,last_name,email,is_staff,is_active,date_joined,favorites,last_played,alias) VALUES ('', (select from_unixtime(unix_timestamp('2018-10-01') + floor(rand() * (unix_timestamp('2019-06-30') - unix_timestamp('2018-01-01') + 1)))), 0, _ID, CONCAT('First', _NM), CONCAT('Middle', _NM), CONCAT('Last',_NM),CONCAT(_NM,i,'@gmail.com'), 0, 1, (select from_unixtime(unix_timestamp('2017-10-01') + floor(rand() * (unix_timestamp('2018-06-30') - unix_timestamp('2017-06-01') + 1)))), '', '', '');
INSERT INTO userprofile (id, profile_image, alias, dob, created_at, gender, age_group, location, updated_at, subscriber_id, state, city, email, dateOfBirth, gamer_name, mobile_no) VALUES (_PRO_ID,'http://www.sample.com/abc.jpg',_NM, _DOB, _CDT, 'M','11-17',NULL, (select from_unixtime(unix_timestamp('2018-10-01') + floor(rand() * (unix_timestamp('2019-06-30') - unix_timestamp('2018-01-01') + 1)))), _ID, NULL, NULL, NULL, NULL, NULL, NULL);
SET _PRO_ID = _PRO_ID +1;
SET i = i + 1;
END WHILE;
END$$
CREATE PROCEDURE delete_test_data()
BEGIN
DELETE FROM userprofile WHERE subscriber_id > 8000009999999999;
DELETE FROM user WHERE subscriber_id > 8000009999999999;
END$$
CREATE PROCEDURE UserArchive(IN before_dt date)
BEGIN
DECLARE cnt int;
DECLARE min_dt date;
DECLARE counter int default 0 ;
DECLARE `_rollback` BOOL DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
SHOW ERRORS;
ROLLBACK;
END;
SELECT COUNT(subscriber_id) INTO cnt FROM `user` WHERE date(last_login) < before_dt;
SELECT min(last_login) INTO min_dt FROM `user` ;
call debug_msg(TRUE, (SELECT concat_ws(' ','Total Records to be migrated:', cnt, 'Loop from:', before_dt,' till (decreasing):', min_dt)));
WHILE before_dt > min_dt do
SET before_dt = DATE_ADD(before_dt, INTERVAL -1 DAY);
SELECT count(subscriber_id) INTO counter FROM user WHERE Date(last_login) = before_dt;
call debug_msg(TRUE, (SELECT concat_ws(' ','Count Subscribers:', counter,' on Date:', before_dt)));
IF counter > 0 THEN
START TRANSACTION;
INSERT INTO userprofile_archived (id, profile_image, alias, dob, created_at, gender, age_group,
location, updated_at, subscriber_id, state, city, email, dateOfBirth, gamer_name, mobile_no)
SELECT
id, profile_image, alias, dob, created_at, gender, age_group, location, updated_at, subscriber_id,
state, city, email, dateOfBirth, gamer_name, mobile_no
FROM userprofile
WHERE subscriber_id IN (SELECT subscriber_id FROM user WHERE Date(last_login) = before_dt);
call debug_msg(TRUE, (SELECT concat_ws(' ','Insertion completed on User Profile table.')));
DELETE FROM userprofile
WHERE subscriber_id IN(
(SELECT subscriber_id FROM user
WHERE Date(last_login) = before_dt));
call debug_msg(TRUE, (select concat_ws(' ','Deletion completed on User Profile table.')));
INSERT INTO user_archived (password, last_login, is_superuser,
subscriber_id, first_name,middle_name,last_name, email, is_staff,
is_active, date_joined, favorites, last_played, alias)
SELECT
password, last_login, is_superuser, subscriber_id, first_name,middle_name,last_name,email,
is_staff,is_active,date_joined,favorites,last_played,alias
FROM user
WHERE Date(last_login) = before_dt;
call debug_msg(TRUE, (select concat_ws(' ','Insertion completed on User table.')));
DELETE FROM user
WHERE Date(last_login) = before_dt;
call debug_msg(TRUE, (select concat_ws(' ','Deletion completed on User table.')));
COMMIT;
END IF;
END WHILE;
END$$
DELIMITER ;