企业宣传,产品推广,广告招商,广告投放联系seowdb

从2s优化到了0.01s 分页查问接口

最近在我的常识星球中,有个小同伴问了这样一个疑问:百万商品分页查问接口,如何保障接口的性能?

这就须要对该分页查问接口做优化了。

这篇文章从9个方面跟大家一同聊聊分页查问接口优化的一些小技巧,宿愿对你会有所协助。

关于分页查问接口,假设没有不凡要求,我们可以在输入参数中,给一些自动值。

这样可以减少数据范畴,防止每次都count一切数据的状况。

关于商品查问,这种业务场景,我们可以自动查问今日上架形态的商品列表。

例如:

select * from productwhere edit_date>='2023-02-20' and edit_date<'2023-02-21' and status=1

假设每天有变卦的商品数量不多,经过这两个自动条件,就能过滤掉绝大局部数据,让分页查问接口的性能优化不少。

分页查问接口通常状况下,须要接纳两个参数:pageNo(即:页码)和pageSize(即:每页大小)。

假设分页查问接口的调用端,没有传pageNo自动值是1,假设没有传pageSize也可以给一个自动值10或许20。

不太倡导pageSize传入过大的值,会间接影响接口性能。

在前端有个下拉控件,可以选用每页的大小,选用范畴是:10、20、50、100。

前端自动选用的每页大小为10。

不过在实践业务场景中,要依据产品需求而且,这里只是一个参考值。

有时刻,我们的分页查问接口的查问结果,须要join多张表能力查出数据。

比如在查问商品信息时,须要依据商品称号、单位、品牌、分类等信息查问数据。

这时刻写一条sql可以查出想要的数据,比如上方这样的:

selectp.id,p.product_name,u.unit_name,b.brand_name,c.category_namefrom product pinner join unit u on p.unit_id = u.idinner join brand b on p.brand_id = b.idinner join category c on p.category_id = c.idwhere p.name='测试商品'limit 0,20;

经常使用product表去join了unit、brand和category这三张表。

其实product表中有unit_id、brand_id和category_id三个字段。

我们可以先查出这三个字段,失掉分页的数据增加范畴,之后再经过主键id汇合去查问额外的数据。

我们可以把sql改成这样:

selectp.id,p.product_id,u.unit_id,b.brand_id,c.category_idfrom productwherelimit 0,20;

这个例子中,分页查问之后,我们失掉到的商品列表其实只需20条数据。

再依据20条数据中的id汇合,失掉其余的称号,例如:

select id,namefrom unitwhere id in (1,2,3);

而后在程序中填充其余称号。

伪代码如下:

List<Product> productList = productMapper.search(searchEntity);List<Long> unitIdList = productList.stream().map(Product::getUnitId).distinct().collect(Collectors.toList());List<Unit> unitList = UnitMapper.queryUnitByIdList(unitIdList);for(Product product: productList) {Optional<Unit> optional = unitList.stream().filter(x->x.getId().equals(product.getId())).findAny();if(optional.isPersent()) {product.setUnitName(optional.get().getName());}}

这样就能有效的增加join表的数量,可以必定的水平上优化查问接口的性能。

分页查问接口性能发生了疑问,最间接最极速的优化方法是:优化索引。

由于优化索引不须要修正代码,只需回归测试一下就行,改变老本是最小的。

我们须要经常使用explain关键字,查问一下消费环境分页查问接口的执行方案。

看看有没有创立索引,创立的索引能否正当,或许索引失效了没。

索引不是创立越多越好,也不是创立越少越好,我们须要依据实践状况,到消费环境测试一下sql的耗时状况,而后选择如何创立或优化索引。

倡导优先创立联结索引。

有时刻我们的业务场景很复杂,有很多查问sql,须要创立多个索引。

在分页查问接口中依据不同的输入参数,最终的查问sql语句,MySQL依据必定的抽样算法,却选用了不同的索引。

不知道你有没有遇到过,某个查问接口,原本性能是没疑问的,但一旦输入某些参数,接口照应期间就十分长。

这时刻假设你此时用explain关键字,检查该查问sql执行方案,会发现如今走的索引,跟之前不一样,并且驱动表也不一样。

之前不时都是用表a驱动表b,走的索引c。

此时用的表b驱动表a,走的索引d。

为了处置Mysql选错索引的疑问,最经常出现的手腕是经常使用force_index关键字,在代码中指定走的索引称号。

但假设在代码中硬编码了,前面一旦索引称号修正了,或许索引被删除了,程序或许会间接报错。

这时该怎样办呢?

答:我们可以经常使用straight_join替代inner join。

straight_join会通知Mysql用左边的表驱动左边的表,能改表优化器关于联表查问的执行顺序。

之前的查问sql如下:

select p.id from product pinner join warehouse w on p.id=w.product_id;...

我们用它将之前的查问sql启动优化:

select p.id from product pstraight_join warehouse w on p.id=w.product_id;...

随着期间的推移,我们的系统用户越来越多,发生的数据也越来越多。

单表曾经抵达了几千万。

这时刻分页查问接口性能急剧降低,我们不能不做分表处置了。

做便捷的分表战略是将历史数据归档,比如:在主表中只保管最近三个月的数据,三个月前的数据,保障到历史表中。

我们的分页查问接口,自动从主表中查问数据,可以将数据范畴增加很多。

假设有不凡的需求,再从历史表中查问数据,最近三个月的数据,是用户关注度最高的数据。

在分页查问接口中,须要在sql中经常使用count关键字查问总记载数。

目前count有上方几种用法:

那么它们有什么区别呢?

由此,最后count的性能从高到低是:

所以,其实count(*)是最快的。

有些时刻,join的表真实太多,没法去掉多余的join,该怎样办呢?

答:可以将数据保管到ClickHouse。

ClickHouse是基于列存储的数据库,不允许事务,查问性能十分高,号称查问十几亿的数据,能够秒级前往。

为了防止对业务代码的嵌入性,可以经常使用Canal监听Mysql的binlog日志。当product表有数据新增时,须要同时查问出单位、品牌和分类的数据,生成一个新的结果集,保管到ClickHouse当中。

查问数据时,从ClickHouse当中查问,这样经常使用count(*)的查问效率能够优化N倍。

其实假设查问条件十分多,经常使用ClickHouse也不是特意适合,这时刻可以改成ElasticSearch,不过它跟Mysql一样,存在深分页疑问。

有时刻,分页查问接口性能差,是由于用户并发量过去了。

在系统的初期,还没有多少用户量,读数据恳求和写数据恳求,都是访问的同一个数据库,该模式成功起来便捷、老本低。

刚开局分页查问接口性能没啥疑问。

但随着用户量的增长,用户的读数据恳求和写数据恳求都显著增多。

我们都知道数据库衔接有限,普通是性能的闲暇衔接数是100-1000之间。假设多余1000的恳求,就只能期待,就或许会发生接口超时的状况。

因此,我们有必要做数据库的读写分别。写数据恳求访问主库,读数据恳求访问从库,从库的数据经过binlog从主库同步过去。

依据不同的用户量,可以做一主一从,一主两从,或一主多从。

数据库读写分别之后,能够优化查问接口的性能。

© 版权声明
评论 抢沙发
加载中~
每日一言
不怕万人阻挡,只怕自己投降
Not afraid of people blocking, I'm afraid their surrender