线上千万级大表排序该如何优化?

2023-11-04 22:20

本文主要是介绍线上千万级大表排序该如何优化?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

  前段时间应急群有客服反馈,会员管理功能无法按到店时间、到店次数、消费金额 进行排序。经过排查发现是Sql执行效率低,并且索引效率低下。遇到这样的情况我们该如何处理呢?今天我们聊一聊Mysql大表查询优化。

应急问题

  商户反馈会员管理功能无法按到店时间、到店次数、消费金额 进行排序,一直转圈圈或转完无变化,商户要以此数据来做活动,比较着急,请尽快处理,谢谢。

线上数据量

merchant_member_info 7000W条数据。
member_info 3000W。

不要问我为什么不分表,改动太大,无能为力。

问题SQL如下

SELECTmui.id,mui.merchant_id,mui.member_id,DATE_FORMAT(mui.recently_consume_time,'%Y%m%d%H%i%s') recently_consume_time,IFNULL(mui.total_consume_num, 0) total_consume_num,IFNULL(mui.total_consume_amount, 0) total_consume_amount,(CASEWHEN u.nick_name IS NULL THEN'会员'WHEN u.nick_name = '' THEN'会员'ELSEu.nick_nameEND) AS 'nickname',u.sex,u.head_image_url,u.province,u.city,u.country
FROMmerchant_member_info mui
LEFT JOIN member_info u ON mui.member_id = u.id
WHERE1 = 1
AND mui.merchant_id = '商户编号'
ORDER BYmui.recently_consume_time DESC / ASC
LIMIT 0,10

出现的原因

  经过验证可以按照“到店时间”进行降序排序,但是无法按照升序进行排序主要是查询太慢了。主要原因是:虽然该查询使用建立了recently_consume_time索引,但是索引效率低下,需要查询整个索引树,导致查询时间过长。

DESC 查询大概需要4s,ASC 查询太慢耗时未知。

为什么降序排序快和而升序慢呢?

  因为是对时间建立了索引,最近的时间一定在最后面,升序查询,需要查询更多的数据,才能过滤出相应的结果,所以慢。

解决方案

目前生产库的索引

调整索引

  需要删除index_merchant_user_last_time索引,同时将index_merchant_user_merchant_ids单例索引,变为 merchant_id,recently_consume_time组合索引。

调整结果(准生产)

调整前后结果对比(准生产)

 测试数据

merchant_member_info 有902606条记录。
member_info 表有775条记录。

SQL执行效率

优化前

优化后

type由index -> ref

ref由 null -> const

TOP优化前优化后
到店时间-降序0.274s0.003s
到店时间-升序11.245s0.003s

调整索引需要执行的SQL

执行的注意事项:
由于表中的数据量太大,请在晚上进行执行,并且需要分开执行。 # 删除近期消费时间索引
ALTER TABLE merchant_member_info DROP INDEX index_merchant_user_last_time;# 删除商户编号索引
ALTER TABLE merchant_member_info DROP INDEX index_merchant_user_merchant_ids;# 建立商户编号和近期消费时间组合索引
ALTER TABLE merchant_member_info ADD INDEX idx_merchant_id_recently_time (`merchant_id`,`recently_consume_time`);

经询问,重建索引花了30分钟。

最终的分页查询优化

  上面的sql虽然经过调整索引,虽然能达到较高的执行效率,但是随着分页数据的不断增加,性能会急剧下降。

分页数据查询时间优化后
limit 0,100.003s0.002s
limit 10,100.005s0.002s
limit 100,100.009s0.002s
limit 1000,100.044s0.004s
limit 9000,100.247s0.016s
最终的sql

优化思路:先走覆盖索引定位到,需要的数据行的主键值,然后INNER JOIN 回原表,取到其他数据。

SELECTmui.id,mui.merchant_id,mui.member_id,DATE_FORMAT(mui.recently_consume_time,'%Y%m%d%H%i%s') recently_consume_time,IFNULL(mui.total_consume_num, 0) total_consume_num,IFNULL(mui.total_consume_amount, 0) total_consume_amount,(CASEWHEN u.nick_name IS NULL THEN'会员'WHEN u.nick_name = '' THEN'会员'ELSEu.nick_nameEND) AS 'nickname',u.sex,u.head_image_url,u.province,u.city,u.country
FROMmerchant_member_info mui
INNER JOIN (SELECTidFROMmerchant_member_infoWHEREmerchant_id = '商户ID'ORDER BYrecently_consume_time DESCLIMIT 9000,10
) AS tmp ON tmp.id = mui.id
LEFT JOIN member_info u ON mui.member_id = u.id

结尾

  如果觉得对你有帮助,可以多多评论,多多点赞哦,也可以到我的主页看看,说不定有你喜欢的文章,也可以随手点个关注哦,谢谢。

  我是不一样的科技宅,每天进步一点点,体验不一样的生活。我们下期见!

这篇关于线上千万级大表排序该如何优化?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

mysql线上查询之前要性能调优的技巧及示例

《mysql线上查询之前要性能调优的技巧及示例》文章介绍了查询优化的几种方法,包括使用索引、避免不必要的列和行、有效的JOIN策略、子查询和派生表的优化、查询提示和优化器提示等,这些方法可以帮助提高数... 目录避免不必要的列和行使用有效的JOIN策略使用子查询和派生表时要小心使用查询提示和优化器提示其他常

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

Deepseek使用指南与提问优化策略方式

《Deepseek使用指南与提问优化策略方式》本文介绍了DeepSeek语义搜索引擎的核心功能、集成方法及优化提问策略,通过自然语言处理和机器学习提供精准搜索结果,适用于智能客服、知识库检索等领域... 目录序言1. DeepSeek 概述2. DeepSeek 的集成与使用2.1 DeepSeek API

Tomcat高效部署与性能优化方式

《Tomcat高效部署与性能优化方式》本文介绍了如何高效部署Tomcat并进行性能优化,以确保Web应用的稳定运行和高效响应,高效部署包括环境准备、安装Tomcat、配置Tomcat、部署应用和启动T... 目录Tomcat高效部署与性能优化一、引言二、Tomcat高效部署三、Tomcat性能优化总结Tom

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

大数据小内存排序问题如何巧妙解决

《大数据小内存排序问题如何巧妙解决》文章介绍了大数据小内存排序的三种方法:数据库排序、分治法和位图法,数据库排序简单但速度慢,对设备要求高;分治法高效但实现复杂;位图法可读性差,但存储空间受限... 目录三种方法:方法概要数据库排序(http://www.chinasem.cn对数据库设备要求较高)分治法(常

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

Python中lambda排序的六种方法

《Python中lambda排序的六种方法》本文主要介绍了Python中使用lambda函数进行排序的六种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1.对单个变量进行排序2. 对多个变量进行排序3. 降序排列4. 单独降序1.对单个变量进行排序