【MySQL】删除重复记录保留一条的高性能DELETE写法

本文主要是介绍【MySQL】删除重复记录保留一条的高性能DELETE写法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


     周中遇到一个情况就是一张表出现了很多重复记录,需要删除掉这些重复记录只保留一条,因为有自增长的主键,就决定保留PK最小的那一条吧。具体操作过程记录如下。


     建一张示例表并插些数据看看吧。

         mysql> CREATE TABLE `visitor_province_yn` (
          ->   `id` INT(11) NOT NULL AUTO_INCREMENT,
          ->   `visitor` int(10) unsigned NOT NULL,
          ->   `province` varchar(25) NOT NULL,
          ->   `yn` CHAR(1) NOT NULL,
          ->   PRIMARY KEY (`id`)
          -> );
         Query OK, 0 rows affected (0.01 sec)

         mysql> INSERT INTO `visitor_province_yn`(`visitor`, `province`, `yn`) VALUES
          -> (11, 'A省', 'Y'),
          -> (11, 'A省', 'Y'),
          -> (11, 'A省', 'Y'),
          -> (22, 'B省', 'N'),
          -> (22, 'B省', 'N'),
          -> (22, 'B省', 'N'),
          -> (33, 'C省', 'Y'),
          -> (33, 'C省', 'Y'),
          -> (33, 'C省', 'Y');
         Query OK, 9 rows affected (0.00 sec)
         Records: 9  Duplicates: 0  Warnings: 0

     示例表“visitor_province_yn”表的数据如下,按照预想是删除重复保留“id”是1、4以及7这三条记录。

mysql> SELECT * FROM `visitor_province_yn`;
+----+---------+----------+----+
| id | visitor | province | yn |
+----+---------+----------+----+
|  1 |      11 | A省      | Y  |
|  2 |      11 | A省      | Y  |
|  3 |      11 | A省      | Y  |
|  4 |      22 | B省      | N  |
|  5 |      22 | B省      | N  |
|  6 |      22 | B省      | N  |
|  7 |      33 | C省      | Y  |
|  8 |      33 | C省      | Y  |
|  9 |      33 | C省      | Y  |
+----+---------+----------+----+
9 rows in set (0.00 sec)

     首先想到的是以下写法,因为DML和DQL是同一张表,不得不额外多一层嵌套子查询。所以,觉得这种写法简单明晰,但是性能应该要有所折扣。

DELETE FROM visitor_province_ynWHERE id NOT IN(SELECT idFROM(SELECT MIN(vpy.id) AS idFROM visitor_province_yn AS vpyGROUP BY vpy.visitor, vpy.province, vpy.yn) AS tmp);

     于是,又去查询了一下MySQL官方手册有关“DELETE”语法的解释(http://dev.mysql.com/doc/refman/5.7/en/delete.html),结果一眼就找到了当前需要的另一种写法,在文档的“Multi-Table Deletes”部分,形式如下。


         DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;


     以此为参考,改写后的SQL如下所示。

DELETE visitor_province_yn
FROM visitor_province_yn
LEFT JOIN(SELECT MIN(vpy.id) AS idFROM visitor_province_yn AS vpyGROUP BY vpy.visitor, vpy.province, vpy.yn) AS tmp USING (id)
WHERE tmp.id IS NULL;

     因此,原来这种左连接返回存在于左表中而不存在于右表中记录的写法同样适用于“DELETE”。“EXPLAIN”一下发现,第二种写法以“PRIMARY”的查询方式代替第一种写法的“DEPENDENT SUBQUERY”,扫描更少的记录行,而且关联方式“type”是性能更优的“ref”(参考译文:http://blog.csdn.net/sweeper_freedoman/article/details/52819839)。由此可见,第二种写法更值得选择。




这篇关于【MySQL】删除重复记录保留一条的高性能DELETE写法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/760365

相关文章

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复

MyBatis编写嵌套子查询的动态SQL实践详解

《MyBatis编写嵌套子查询的动态SQL实践详解》在Java生态中,MyBatis作为一款优秀的ORM框架,广泛应用于数据库操作,本文将深入探讨如何在MyBatis中编写嵌套子查询的动态SQL,并结... 目录一、Myhttp://www.chinasem.cnBATis动态SQL的核心优势1. 灵活性与可

MySQL 表的内外连接案例详解

《MySQL表的内外连接案例详解》本文给大家介绍MySQL表的内外连接,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录表的内外连接(重点)内连接外连接表的内外连接(重点)内连接内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我

MySQL的ALTER TABLE命令的使用解读

《MySQL的ALTERTABLE命令的使用解读》:本文主要介绍MySQL的ALTERTABLE命令的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、查看所建表的编China编程码格式2、修改表的编码格式3、修改列队数据类型4、添加列5、修改列的位置5.1、把列

Mybatis嵌套子查询动态SQL编写实践

《Mybatis嵌套子查询动态SQL编写实践》:本文主要介绍Mybatis嵌套子查询动态SQL编写方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、实体类1、主类2、子类二、Mapper三、XML四、详解总结前言MyBATis的xml文件编写动态SQL

解决mysql插入数据锁等待超时报错:Lock wait timeout exceeded;try restarting transaction

《解决mysql插入数据锁等待超时报错:Lockwaittimeoutexceeded;tryrestartingtransaction》:本文主要介绍解决mysql插入数据锁等待超时报... 目录报错信息解决办法1、数据库中执行如下sql2、再到 INNODB_TRX 事务表中查看总结报错信息Lock

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

MySQL 安装配置超完整教程

《MySQL安装配置超完整教程》MySQL是一款广泛使用的开源关系型数据库管理系统(RDBMS),由瑞典MySQLAB公司开发,目前属于Oracle公司旗下产品,:本文主要介绍MySQL安装配置... 目录一、mysql 简介二、下载 MySQL三、安装 MySQL四、配置环境变量五、配置 MySQL5.1

MySQL 添加索引5种方式示例详解(实用sql代码)

《MySQL添加索引5种方式示例详解(实用sql代码)》在MySQL数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中,下面给大家分享MySQL添加索引5种方式示例详解(实用sql代码),... 在mysql数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中。索引可以在创建表时定义,也可