忘记密码   免费注册 查看新帖 | 论坛精华区
ChinaUnix.net
  平台论坛 博客 微博 读书 人才 精华 文库 自测 | 频道操作系统 开发 数据库 存储 服务器 网络 IT新闻 Linux 下载 Power用户组
最近访问板块 发新帖
查看: 3937 | 回复: 14

mysql关联删除记录问题 [复制链接]

Rank: 2

帖子
138
主题
19
精华
0
可用积分
1936
专家积分
0
在线时间
361 小时
注册时间
2006-09-10
最后登录
2011-06-22
论坛徽章:
0
发表于 2009-05-14 00:18:58 |显示全部楼层
有俩个表table1 , table2

talbe1   有俩个字段id,pid     有2千万条记录         同一pid对应多个id
table2   有一个字段pid         有100万条记录        pid唯一

想要删除表table1中记录,条件是table1.pid=table2.pid

大家给推荐一个效率高一点的方法,用delete表关联删除效率不是很高,感觉有点慢

[ 本帖最后由 steel_lei 于 2009-5-14 00:23 编辑 ]

Rank: 3Rank: 3

帖子
500
主题
18
精华
0
可用积分
3364
专家积分
0
在线时间
281 小时
注册时间
2007-12-16
最后登录
2011-11-14
论坛徽章:
0
发表于 2009-05-14 09:29:20 |显示全部楼层
我想到的是select建新表,但是好像也快不了多少

CREATE TABLE tmp AS  SELECT  * FROM table1  WHERE pid NOT IN (SELECT pid FROM table2)

Rank: 2

帖子
138
主题
19
精华
0
可用积分
1936
专家积分
0
在线时间
361 小时
注册时间
2006-09-10
最后登录
2011-06-22
论坛徽章:
0
发表于 2009-05-14 09:43:46 |显示全部楼层
原帖由 ws00377531 于 2009-5-14 09:29 发表
我想到的是select建新表,但是好像也快不了多少

CREATE TABLE tmp AS  SELECT  * FROM table1  WHERE pid NOT IN (SELECT pid FROM table2)


我在测试创建表,看一下create的效率,但后面没用not in,用not in会很慢的,用表关联会好很多

Rank: 8Rank: 8

帖子
13649
主题
1525
精华
16
可用积分
1775
专家积分
176
在线时间
4564 小时
注册时间
2005-01-11
最后登录
2012-01-27
论坛徽章:
0
发表于 2009-05-14 09:52:19 |显示全部楼层
not in 更慢的了,关连要快。看索引了。

知我者谓我心忧,不知我者谓我何求

Rank: 2

帖子
376
主题
14
精华
2
可用积分
1166
专家积分
0
在线时间
684 小时
注册时间
2005-06-15
最后登录
2011-08-30
论坛徽章:
0
发表于 2009-05-14 09:55:43 |显示全部楼层
改用left join吧
SELECT  * FROM table1 a left join table2 b on (a.pid=b.pid) where b.pid is null

Rank: 8Rank: 8

帖子
13649
主题
1525
精华
16
可用积分
1775
专家积分
176
在线时间
4564 小时
注册时间
2005-01-11
最后登录
2012-01-27
论坛徽章:
0
发表于 2009-05-14 10:14:48 |显示全部楼层
原帖由 voxxu 于 2009-5-14 09:55 发表
改用left join吧
SELECT  * FROM table1 a left join table2 b on (a.pid=b.pid) where b.pid is null

这个好。

知我者谓我心忧,不知我者谓我何求

Rank: 8Rank: 8

帖子
1166
主题
109
精华
2
可用积分
21511
专家积分
0
在线时间
822 小时
注册时间
2003-10-11
最后登录
2012-01-05
论坛徽章:
0
发表于 2009-05-14 10:16:43 |显示全部楼层
对于一个2000W的大表,一次走一个全表扫描确是很困难的。不过对于100W的表走一个全描扫也困难。

如果做这件事情又不想影响太大,就要分步来完成。

我给你一个思路你来参考一下。
首先衡量删除操作有多大。
selet count(*) from table1 a ,table2 b where a.pid=b.pid;
如果都有索引的话,这个操作还是挺快的。
如果操作的操作大于原表的40%,那么很有必要重建这个表了。

重建表的方法:就是按条件提取数据到一个新表,最后改名完成。这是一种方案。

另一种 删除方向。

上面通过比较觉的需要删除的量不是太大时,把需要删除的PID生到到另一个临时表中。
mysql DBname -e "select a.pid from table1 a ,table2 b where a.pid=b.pid">del_pid.txt;

sed -i '1d' del_pid.txt
awk '{print "delete from table1 where pid=",$1,";"}' del_pid.txt >del_pid.sql
mysql DBname<del_pid.sql

这样把SQL拆成多个SQL执行速度应该不会太慢了。

如果还是感觉不行,那就只能分段操作了。
http://www.mysqlsupport.cn
MySQL 支持
专注MySQL优化,架构设计

Rank: 8Rank: 8

帖子
13649
主题
1525
精华
16
可用积分
1775
专家积分
176
在线时间
4564 小时
注册时间
2005-01-11
最后登录
2012-01-27
论坛徽章:
0
发表于 2009-05-14 10:30:47 |显示全部楼层

回复 #7 Coolriver 的帖子

这个很好,我们经常也这样做,用perl..

不过一般我是数据库做的事情让数据库做。

知我者谓我心忧,不知我者谓我何求

Rank: 8Rank: 8

帖子
1166
主题
109
精华
2
可用积分
21511
专家积分
0
在线时间
822 小时
注册时间
2003-10-11
最后登录
2012-01-05
论坛徽章:
0
发表于 2009-05-14 17:04:05 |显示全部楼层
原帖由 枫影谁用了 于 2009-5-14 10:30 发表
这个很好,我们经常也这样做,用perl..

不过一般我是数据库做的事情让数据库做。

我现在很多工作拿到数据外面做了。
数据量大了,全压到DB上,都出不了结果了。:)
http://www.mysqlsupport.cn
MySQL 支持
专注MySQL优化,架构设计

Rank: 7Rank: 7Rank: 7

帖子
1450
主题
79
精华
1
可用积分
16838
专家积分
134
在线时间
2056 小时
注册时间
2008-04-11
最后登录
2011-11-26
论坛徽章:
0
发表于 2009-05-14 17:55:06 |显示全部楼层
原帖由 Coolriver 于 2009-5-14 10:16 发表
对于一个2000W的大表,一次走一个全表扫描确是很困难的。不过对于100W的表走一个全描扫也困难。

如果做这件事情又不想影响太大,就要分步来完成。

我给你一个思路你来参考一下。
首先衡量删除操作有多大 ...


很不错~收藏了~但是把id放到临时文件里会有效率问题吗?跟建个临时表存id,哪个好一点?
MSN: lulu22_25@hotmail.com
到点评团淘便宜
-----------------------------
您需要登录后才可以回帖 登录 | 注册

北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP