删除MySQL重复数据的方法_Mysql

本文实例讲述了删除MySQL重复数据的方法。分享给大家供大家参考。具体方法如下:

项目背景

在最近做的一个linux性能采集项目中,发现线程的程序入库很慢,再仔细定位,发现数据库里面很多冗余数据。因为在采集中,对于同一台设备,同一个时间点应该只有一个数据,然而,数据库中存入了多个数据。对于如何造成了这个结果,一时没有想清楚,但为了解决入库慢的问题,首先要删除冗余数据。

问题描述

数据库的表结构很简单,如下:

复制代码 代码如下:

+----------------+--------------+------+-----+---------+-------+
| Field          | Type         | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id             | varchar(255) | NO   | PRI | NULL    |       |
| conf_id        | varchar(255) | NO   | MUL | NULL    |       |
| insert_time    | datetime     | YES  |     | NULL    |       |
| cpu_usage      | float(11,2)  | YES  |     | NULL    |       |
| memory_usage   | float(11,2)  | YES  |     | NULL    |       |
| io_usage_write | float(11,2)  | YES  |     | NULL    |       |
| io_usage_read  | float(11,2)  | YES  |     | NULL    |       |
+----------------+--------------+------+-----+---------+-------+

查询所有数据量

复制代码 代码如下:

select count(*) from perf_linux;

输出 427366

查询所有时间点不同设备的数据量

复制代码 代码如下:

select count(distinct conf_id, insert_time) from perf_linux ;

输出42387

由上面的数据可以看出,数据冗余了10倍左右。

再按时间分组看一下:

复制代码 代码如下:

select id, conf_id ,insert_time from perf_linux order by insert_time, conf_id;

输出:

复制代码 代码如下:

| 2a79f7cd-43a9-4c7b-adb2-316b6c04283e | 1       | 2014-12-09 15:09:14 |
| 50d6f6c2-9c8b-45fd-98fd-2be211221cfd | 1       | 2014-12-09 15:09:14 |
| 740b52e1-e868-4074-ba36-74e2634401b3 | 1       | 2014-12-09 15:09:14 |
| 8b0096a4-9e85-417b-a131-e3505ca79a9c | 1       | 2014-12-09 15:09:14 |
| 90a9e882-5220-4508-a56f-8d4ab4a7929b | 1       | 2014-12-09 15:09:14 |
| d17403ed-24a4-45e8-b51b-2a95118383d9 | 1       | 2014-12-09 15:09:14 |
| 0c2da917-579b-4080-857d-7159f38b44ac | 2       | 2014-12-09 15:09:14 |
| 263083eb-8f63-4d2b-a03f-3320aa678735 | 2       | 2014-12-09 15:09:14 |
| d6c57a38-080b-465a-a55a-beafd9daf32d | 2       | 2014-12-09 15:09:14 |
| f672227b-1fb8-4b85-880d-2cc34b02880d | 2       | 2014-12-09 15:09:14 |
| f80020fe-6cb5-48ec-beb0-4e8ebeb0ca57 | 2       | 2014-12-09 15:09:14 |
| ff633a35-824d-49ba-b78c-5bcc5df8d1cc | 2       | 2014-12-09 15:09:14 |
| 5c41e48a-abfc-4108-a00e-ca7def7d5a5a | 3       | 2014-12-09 15:09:14 |
| 60b7ab9e-c91a-4020-a6d3-7bceb1dc47c5 | 3       | 2014-12-09 15:09:14 |
| 7b6cd2b8-ac6d-43eb-8858-e15885e676c8 | 3       | 2014-12-09 15:09:14 |
| d53a3df5-08c4-4604-8fac-cb51077935f6 | 3       | 2014-12-09 15:09:14 |
| d9e4ba14-f98d-42a8-b3bc-2879d58aa797 | 3       | 2014-12-09 15:09:14 |
| f56f82f6-32a7-47f7-ae07-b13168743884 | 3       | 2014-12-09 15:09:14 |
| 076c4c1b-0028-4a9c-a8c4-de655bd6ab6b | 4       | 2014-12-09 15:09:14 |
| 2a90ad9e-11a5-4707-95e8-78491da658ad | 4       | 2014-12-09 15:09:14 |
| 3b17ad1d-e589-4b65-93a7-d61fc99b4071 | 4       | 2014-12-09 15:09:14 |
| 6988d6cf-44ef-47f7-808d-09791caf2d90 | 4       | 2014-12-09 15:09:14 |
| 8404d281-f9e5-4153-a47e-128c05386758 | 4       | 2014-12-09 15:09:14 |
| e042e310-7ff2-4e4d-8c98-71e3e4d57828 | 4       | 2014-12-09 15:09:14 |
+--------------------------------------+---------+---------------------+

由上图可见,同一个时间点的同一个设备的数据有冗余,现在我们要把这些冗余数据去掉。

解决方法

思路是这样的:首先应该按照conf_id和时间点来判断,进行分组(group by)查询,每组中再取一个就可以。分组是很简单,但是分组怎么取一个呢?我采用了中间表的形式。

创建中间表,并把数据导入中间表

复制代码 代码如下:

create table perf_linux_t like perf_linux;
insert into perf_linux_t select * from perf_linux;

在中间表中增加一个字段,此字段是自增长的。

复制代码 代码如下:

ALTER TABLE `perf_linux_t`
ADD COLUMN `auto_id` INT NOT NULL AUTO_INCREMENT ,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`auto_id`);

删除无用数据

先查询一下

复制代码 代码如下:

select min(auto_id) as auto_id from perf_linux_t group by insert_time ;

删除不对的数据

复制代码 代码如下:

delete  from perf_linux_t where auto_id not in (select min(auto_id) as auto_id from perf_linux_t group by insert_time);

慢着,输出错误:

You can't specify target table 'perf_linux_t' for update in FROM clause

不能删除啊,那只能再建一个中间表了。

再建中间表

复制代码 代码如下:

create table tmp like perf_linux_t;

转变思路,不删除不符合的数据,而是把符合的数据存到这张新表中。

复制代码 代码如下:

insert into tmp select * from perf_linux_t where auto_id in (select min(auto_id) as auto_id from perf_linux_t group by insert_time,conf_id );

把这张表中的无用列删除

复制代码 代码如下:

ALTER TABLE `tmp`
DROP COLUMN `auto_id`,
DROP PRIMARY KEY;

导回数据

删除原来的数据

复制代码 代码如下:

truncate table perf_linux;

插入数据

复制代码 代码如下:

insert into perf_linux select * from tmp;

删除中间表

复制代码 代码如下:

drop table tmp;
drop table perf_linux_t;

总结

通过这个方法,数据变为了42387条,删除了冗余的数据。但实际上程序的问题并没有完全定位,还需要观察才能定位问题。

希望本文所述对大家的mysql数据库程序设计有所帮助。

时间: 2024-10-03 18:03:45

删除MySQL重复数据的方法_Mysql的相关文章

删除MySQL重复数据

原文:删除MySQL重复数据 删除MySQL重复数据 项目背景 在最近做的一个linux性能采集项目中,发现线程的程序入库很慢,再仔细定位,发现数据库里面很多冗余数据.因为在采集中,对于同一台设备,同一个时间点应该只有一个数据,然而,数据库中存入了多个数据.对于如何造成了这个结果,一时没有想清楚,但为了解决入库慢的问题,首先要删除冗余数据. 问题描述 数据库的表结构很简单,如下: +----------------+--------------+------+-----+---------+--

MySQL处理重复数据的方法_Mysql

有些 MySQL 数据表中可能存在重复的记录,有些情况我们允许重复数据的存在,但有时候我们也需要删除这些重复的数据. 本章节我们将为大家介绍如何防止数据表出现重复数据及如何删除数据表中的重复数据.防止表中出现重复数据 你可以在MySQL数据表中设置指定的字段为 PRIMARY KEY(主键) 或者 UNIQUE(唯一) 索引来保证数据的唯一性. 让我们尝试一个实例:下表中无索引及主键,所以该表允许出现多条重复记录. CREATE TABLE person_tbl ( first_name CHA

Python增量循环删除MySQL表数据的方法_python

需求场景: 有一业务数据库,使用MySQL 5.5版本,每天会写入大量数据,需要不定期将多表中"指定时期前"的数据进行删除,在SQL SERVER中很容易实现,写几个WHILE循环就搞定,虽然MySQL中也存在类似功能,怎奈自己不精通,于是采用Python来实现 话不多少,上脚本: # coding: utf-8 import MySQLdb import time # delete config DELETE_DATETIME = '2016-08-31 23:59:59' DELE

分享MYSQL插入数据时忽略重复数据的方法_Mysql

使用下以两种方法时必须把字段设为"主键(PRIMARY KEY"或"唯一约束(UNIQUE)".1:使用REPLACE INTO (此种方法是利用替换的方法,有点似类于先删除再插入)  复制代码 代码如下: REPLACE INTO Syntax  REPLACE [LOW_PRIORITY | DELAYED]      [INTO] tbl_name [(col_name,...)]      {VALUES | VALUE} ({expr | DEFAULT}

快速删除Excel重复数据的方法

  1.我先打开我工作中的一个excel工作表,如下图所示我们会看到表的 第2行和第7行,第3行和第6行内容完全相同: 2.选中表中的所有记录,包括A与B标题了,要不之后会看不到标题了. 3.选中之后我们点击菜单栏上的"数据"菜单→"筛选→高级筛选" 如下图所示. 4.在弹出的高级筛选对话框中我们选中"将筛选结果复制到其他位置"一项,然后接着点击"复制到"选择框后面的范围按钮来选择一块区域以存放筛选后的数据 ,记住不要与原数据

PHP查询并删除数据库多列重复数据的方法(利用数组函数实现)_php技巧

本文实例讲述了PHP查询并删除数据库多列重复数据的方法.分享给大家供大家参考,具体如下: <?php $con = mysql_connect("localhost","root",""); if (!$con) { die('Could not connect: ' . mysql_error()); } $db_selected = mysql_select_db("test_db", $con); if (!$db

Yii+MYSQL锁表防止并发情况下重复数据的方法_php实例

本文实例讲述了Yii+MYSQL锁表防止并发情况下重复数据的方法.分享给大家供大家参考,具体如下: lock table 读锁定 如果一个线程获得在一个表上的read锁,那么该线程和所有其他线程只能从表中读数据,不能进行任何写操作. lock tables user read;//读锁定表 unlock tables;//解锁 lock tables user read local;//本地读锁定表,其他线程的insert未被阻塞,update操作被阻塞 lock table 写锁定 如果一个线

Yii+MYSQL锁表防止并发情况下重复数据的方法

本文实例讲述了Yii+MYSQL锁表防止并发情况下重复数据的方法.分享给大家供大家参考,具体如下: lock table 读锁定 如果一个线程获得在一个表上的read锁,那么该线程和所有其他线程只能从表中读数据,不能进行任何写操作. lock tables user read;//读锁定表 unlock tables;//解锁 lock tables user read local;//本地读锁定表,其他线程的insert未被阻塞,update操作被阻塞 lock table 写锁定 如果一个线

MSSql简单查询出数据表中所有重复数据的方法_MsSql

本文实例讲述了MSSql简单查询出数据表中所有重复数据的方法.分享给大家供大家参考,具体如下: 这里直接给出下面的例子: SELECT * FROM SYS_LogContent slc WHERE slc.LogInfo_ID IN ( SELECT slc2.LogInfo_ID FROM SYS_LogContent slc2 GROUP BY slc2.LogInfo_ID HAVING COUNT(*)>1 ) 简单说明: 关键代码在于上面的括号中.要想查询出所有重复的数据,可以按照某