mysql分页limit偏移量过大优化和删除重复数据中id小的数据

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_23888451/article/details/82261768

今天看到关于MySQL两道题:

create table test(
id int(11) not NULL AUTO_INCREMENT,
title varchar(50) DEFAULT NULL COMMENT '标题',
value varchar(50) DEFAULT NULL COMMENT '值',
createTime timestamp not NULLDEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
proId int(11) DEFAULT NULL COMMENT '产品外键id',
sta int(1) DEFAULT 1 COMMENT '状态',
PRIMARY KEY(id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

1.如何优化分页SQL,改写SQL:select * from test where sta=1 limit 600000,10;
2.找出重复的proId及个数,并删除重复数据中id最小的那条数据。

解析1:
limit用在分页上,当数据量够小时,也许感觉不到limit语句的性能问题,但当数据达到几百万时,性能会急剧下降,可能卡死服务器。
比如题中的“limit 600000,10”表示从第600001万条数据开始查,返回10条,问题就在这,已经扫描了满足条件的600020条,扔掉前面600000行,返回有效的10条,难怪会卡死。下面对SQL进行优化:

select * from (
select id
from test where sta=1 order by id limit 600000,10
) a
left join test b on a.id=b.id

说明一下,这里用到字段sta、id需要把这两个字段做复合索引,否则效果提升不明显。当一个数据库表过于庞大,limit offset,length中的offset值过大时,则SQL查询语句会非常缓慢,需增加order by,并且order by字段需要建立索引
如果查询的记录比较大,并且数据传输量比较大,比如包含了text类型的字段,则可以建立子查询。

select id,title,content 
from test 
where id in (select id from test order by id limie 600000,10)

如果offset的值较大,可以通过传递pk值来减小offset=0,这个主键最好是int类型并且是auto_increment,比如

select * from test 
where id>=(select id from test order by id limit 600000,1) 
limit 0,10;

参考:https://www.cnblogs.com/shiwenhu/p/5757250.html
解析2

查找重复的proId及个数
select proId,count(*)
from test 
group by proId
having count(*)>1
删除重复数据中id最小的那条

1创建临时表

create temporary table temp as
select min(id) as minid from test group by proId;

delete from test where id in (select id from temp);

2直接在原表操作

delete from test where id in (
select min(id) from test group by proId
);

执行报错:更新数据时使用了查询,而查询数据又做了更新的条件,mysql不支持这种方式
再加一层封装,如下:

delete  from test where id in (
select minid from (
    select min(id) minid from test group by proId
) b

参考:https://www.cnblogs.com/nzbbody/p/4470638.html

猜你喜欢

转载自blog.csdn.net/qq_23888451/article/details/82261768