mysql表刪除重複記錄方法總結及效率對比

下面這些方法在我虛擬機上做的測試,內存384M,交換分區1024M, test共300W數據,重複記錄3.5W,需求如題目所示,表結構如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CREATE DATABASE /*!32312 IF NOT EXISTS*/`test` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `test`;
/*Table structure for table `test` */
DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(20) DEFAULT NULL COMMENT '姓名',
`age` tinyint(4) DEFAULT NULL COMMENT '年齡',
`mate` tinyint(4) DEFAULT '1'COMMENT '有無配偶(1-有 0-無)',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`),
KEY `idx_age` (`age`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;

現有記錄:

1
2
3
4
5
6
7
8
insert  into `test`(`id`,`name`,`age`,`mate`) values (2,'aaaaa',28,0),
(3,'bbbb',23,0),
(4,'cccc',25,1),
(5,'dddd',26,0),
(6,'eeee',24,0),
(7,'fffff',18,0),
(8,'eeee',40,1),
(9,'eeee',60,1);

想去掉name重名的記錄,方法如下:
  1.給name字段修改成唯一索引:

1
2
drop index idx_name on test;
alter table test add unique index (name);

這樣當向表中添加相同記錄的時候,會返回1062的添加失敗信息。
但是有一種情況是表中已經有n個重複的記錄,這時候我們纔想起來要添加唯一索引,再執行上面的操作時,數據庫會告訴你已經有重複的記錄了,建立索引失敗,這時候,我們可以用下面的操作:

1
alter ignore table test add unique idx_name (name);

它會刪除重複的記錄(別怕,會保留一條),然後建立唯一索引,高效而且人性化。
   2.重建表方法一:
創建另外一個表,爲了防止原來的表結構丟失,可以先創建一個這樣的”臨時表”,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
USE `test`;
/*Table structure for table `test` */
DROP TABLE IF EXISTS `uniq_test`;
CREATE TABLE `uniq_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(20) DEFAULT NULL COMMENT '姓名',
`age` tinyint(4) DEFAULT NULL COMMENT '年齡',
`mate` tinyint(4) DEFAULT '1'COMMENT '有無配偶(1-有 0-無)',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`),
KEY `idx_age` (`age`)
) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

從test表中查找數據,添加到uniq_test中:

1
2
3
insert into uniq_test select * from test group by name;
drop table test;
rename table uniq_test to test;

3.刪除重複記錄法:
創建一個表用來存放,要刪除的記錄的id信息:

1
2
3
4
CREATE TABLE `tmp_ids` (
`id` int(11),
`name` char(20)  
) ENGINE=MyISAM;

如果要刪除的記錄不多的話,可以把這個表創建成內存表形式:

1
2
3
4
CREATE TABLE `tmp_ids` (
`id` int(11),
`name` char(20)
) ENGINE=HEAP;

然後在test表中刪除重複記錄:

1
2
3
insert into tmp_ids select min(id),name from test group by name having count(*)>1 order by null;
deletea.* from test a,tmp_ids b where b.name=a.name anda.id>b.id;
truncate table tmp_ids;

4.效率低下方法

1
2
3
4
5
6
7
8
9
DELETEtest AS a  FROM test AS a,
(
SELECT *
FROM  test
GROUP BY name
HAVING count(1) >1
order by null
) AS b
WHERE a.name = b.name AND a.id > b.id;

總結:
第一種方法歷史22分鐘,系統負載5左右;
第二種方法效率非常低下,把未知索引文件破壞,終止執行
第三種方法歷時17分鐘,其中

1
insert into tmp_ids select min(id),name from test group by name having count(*)>1 order by null

歷時15分鐘,刪除動作歷時2分鐘,系統負載3左右
第四種方法,執行過程中,把它test的索引文件都破壞了,可見”威力”之大。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章