业务背景

最近一个开发维护的公众号管理系统用户表(user_info)数据已经达到15,000k了,而此时有一个业务场景需要将公众号的用户信息重新同步一次,且后台原有过针对单个公众号的用户同步,但是已经非常难以使用,因为同步时间太长了,以前的同步用户方式大概流程如下:

通过上面的流程可以看出来更新用户流程过程非常耗时,每个用户更新下来应该需要300ms左右,因为这涉及到每次更新一个用户都需要调用一次微信接口,然后单个更新用户信息又分两步a.查询用户是否存在、b.不存在则更新。其中user_info表已经针对openid建立了普通索引,查询起来比较快。那么一个30W粉丝的公众号数据更新可能就需要14hour左右,这个时间是无法接受的。那么应该如何来进行优化呢?很明显可以这下面两点开始:
1. 拉取微信用户信息使用批量接口,批量接口一次可以拉取100个用户信息;
2. 插入用户数据使用批量插入、更新接口每次可以插入100条(这个数量如何确定的?其实只要数据库插入的时间和拉取用户数据差不多就可以了,没必要一次插入几千、几万条,因为接口数据如何没有准备好的话该过程也是在等待)。

上面两点可以优化性能,其中第一点没什么好说的调用公众平台的批量接口,第二代批量插入数据库,而且要求:用户存在时更新用户信息、用户不存在时插入用户信息。

可以用下面语句满足上面业务:

insert into tableName(id,name1,name12) values (a,b,c),(d,c,e) on DUPLICATE KEY UPDATE name1=values(name1),name2=values(name2)

Mybaits写法


<insert id="batchInsert">insert into tableName(id,name1,name12) values <foreach collection="List" item="item" index="index" separator=",">(#{item.id,jdbcType=VARCHAR},#{item.name1,jdbcType=VARCHAR},#{item.name2,jdbcType=VARCHAR}) </foreach>ON DUPLICATE KEY UPDATE name1=values(name1),name2=values(name2)
</insert>

上面满足业务需要的insert sql语句建立在数据有唯一索引的情况下,例如要限制插入用户信息不重复那么需要针对openid来创建唯一索引才能满足需求。这个时候问题就来了,如何修改千万级别的数据表索引呢?而且该数据表还是一个业务活跃表。

服务器性能

8核16G 300G SSD 云主机 性能还过的去其他网卡什么的不用考虑太多同机房应用服务器这些不是性能瓶颈,主要是唯一索引过程需要排序要消耗不少CPU。

建索引前准备

这种千万级别的==活跃==数据表肯定需要找专家一起评估一番才敢开始动手,于是第一步找有经验的DBA同事一起协商下根据当前数据服务器性能、数据量、业务请求等多方面评估修改索引的风险和影响。根据历史经验DBA给除了几分钟肯定不行的评估,让我直接建。然后就是业务方面的评估,索引期间对业务的影响,因为索引过程中会导致数据服务器性能变慢,因此我们决定找一个用户不太活跃的时间段来开始。那么接下来就是准备步骤了。整理大致步骤如下:

  1. 找出user_info表 openid重复的数据;
  2. 重复数据只保留一条;
  3. 删除openid普通索引;
  4. 创建openid唯一索引。

开始执行

由于历史遗留问题,实际操作步骤更为复杂:
1. create table user_info_duplicate like user_info; //创建临时表用来备份重复数据
2. insert into user_info_duplicate select * from user_info group by openid having count(*) > 1;
3. SELECT openid from user_info_duplicate; //导出重复的openid到文件(用子查询的方式删除会特别慢)
4. 提供删除openid的脚本文件提执行sql
5. 删除openid为null的数据

DELETE from user_info where openid is null;

DELETE from user_info_duplicate where openid is null;

  1. drop INDEX openid_index on user_info; //删除旧索引;
  2. ALTER TABLE user_info ADD UNIQUE openid_u_index(openid); // 创建唯一索引;
    8、insert ignore into user_info select * from user_info_duplicate; //把数据还原

总结

其中有几个步骤需要特别说明下:
- 第一是重复数据部分之后要先创建唯一索引再还原数据否则怕在业务过程中被删除的用户更新了用户表导致基于openid的唯一索引创建失败;
- 另外需要关注的是第6和第7步应该更换一下位置,否则会导致业务非常缓慢,因为在很多业务依赖索引openid_index来执行时,突然索引被清除了那么千万基本的表肯定会有大量的查询超时,导致业务异常,我们就是按照这个悲剧式的步骤执行的,果然最后悲剧了;
- 最后异步还原数据的时候要用ignore关键字避免插入重复的数据,因为在创建索引过程中由于业务在执行可能会有与备份表相同的用户进入业务系统更新用户表(进入公众号进行操作时会自动更新用户信息到数据库)

最终数据库索引创建过程花了大概 36min。性能不错的虚拟机花费了这么长时间,这个过程中业务一直超时,还好执行时间段用户比较少,影响不是特别大。真是一个不小的教训。

Query OK, 0 rows affected (36 min 13.23 sec)
Records: 0  Duplicates: 0  Warnings: 0

最后更新系统代码为批量更新,300,000K 用户更新花费了大概 1hour,更新速度提升了10+倍。基本上面是每100调用户花费1s更新。

千万级别数据表创建索引相关推荐

  1. mySQL数据表创建索引_MySQL创建数据表 建索引

    除非注明,文章均为易水寒原创,版权属于易水寒博客,转载请注明出处,谢谢. 三.数据字段属性: 1.unsigned 可以让空间增加一倍,如果不希望在字段中插入负值就使用此属性,另外只能用在数值型字段. ...

  2. MySQL为数据创建索引的目的_为数据表创建索引的目的是什么

    一.SQL创建索引的目的如下: 1.通过唯一性索引(unique)可确保数据的唯一性: 2.加快数据的检索速度: 3.加快表之间的连接: 4.减少分组和排序时间: 5.使用优化隐藏器提高系统性能. 二 ...

  3. B+Tree索引为什么可以支持千万级别数据量的查找——讲讲mysql索引的底层数据结构

    MySQL索引底层数据结构 索引是存储引擎快速找到记录的一种数据结构 一. 有索引与没索引的差距 先来看一张图: 左边是没有索引的情况,右边是作为col2字段 二叉树索引的情况. 假如执行查找(假设表 ...

  4. 数据库建立索引、数据表创建规则、备用字段 / 保留字段 / 预留字段

    数据库建立索引 数据库.数据表建立索引的原则 数据库建立索引的原则 1,确定针对该表的操作是大量的查询操作还是大量的增删改操作. 2,尝试建立索引来帮助特定的查询.检查自己的sql语句,为那些频繁在w ...

  5. mysql数据库千万级别数据的查询优化和分页测试

    原文地址:原创 mysql数据库千万级别数据的查询优化和分页测试作者:于堡舰  本文为本人最近利用几个小时才分析总结出的原创文章,希望大家转载,但是要注明出处  http://blog.sina.co ...

  6. mysql插入数据返回主键值_Mysql千万级别数据批量插入只需简单三步!

    第一步:配置my.ini文件 文件中配置 bulk_insert_buffer_size=120M 或者更大 将insert语句的长度设为最大. Max_allowed_packet=1M Net_b ...

  7. 【Robo3T】为mongodb数据库中的表创建索引的步骤

    [Robo3T]为mongodb数据库中的表创建索引的步骤 MongoDB 索引 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条 ...

  8. oracle创建索引表,Oracle 大表创建索引

    Oracle 大表创建索引 祖仙教小凡仙 海鲨数据库架构师 有个2亿记录的表,发现需要添加一个联合索引,结果就采用普通的create index index_name on tablename (en ...

  9. B-Tree/B+-Tree/二叉树/红黑树/Hash表/MySQL底层到底用哪个数据表建立索引做快速查找?

    B-Tree/B+-Tree/二叉树/红黑树/Hash表/MySQL底层到底用哪个数据表建立索引做快速查找? ~~B-Tree~~ ==B+Tree== ~~二叉树(Binary Search Tre ...

最新文章

  1. 22省份公务员考试开考,个别职位竞争比达2624:1
  2. respect labor
  3. 常见Java面试题之JVM加载class文件的原理机制
  4. 前端学习(2164):runtimeonly和runtimecompiler
  5. hive当前日期超前_微博数仓数据延时优化方案
  6. 通信原理 | 信道的概念和实际信道
  7. vue基础----用vue来展示表格数据
  8. 怎么获取jquery版本_获取jQuery版本
  9. linux系统双网卡不能同时启动,针对RHEL中双网卡IP不能同时被访问的解决方法
  10. 大数据的处理是怎样的过程
  11. 暑假计算机教育培训总结,暑假信息技术培训心得
  12. 从0开始学大数据(一)
  13. 微信浏览器(jssdk)自定义分享按钮,自定义链接,图片,描述等
  14. 关于模型的评估指标(超详细)
  15. 问卷调查系统的设计与实现【源码:文档:教程】
  16. 股票买到手想卖可以随时都能卖掉吗
  17. 《数据统计分析及R语言编程(第二版)》练习题总结(一)
  18. PID控制通俗解释与PID参数的整定方法--以温控系统为例
  19. sitemesh 使用方法
  20. matlab分布函数逆函数,MATLAB如何使用icdf函数计算指定分布的逆累积分布

热门文章

  1. 2021-03-30 CodeCraft-21 and Codeforces Round #711 (Div. 2)
  2. [基本功]卡方分布、卡方检验、卡方分箱
  3. 1409: 矩阵乘积
  4. 终于见到你了,中国天眼!
  5. HCIA-存储虚拟化
  6. 基于MOS管的防反接电路设计仿真
  7. edge-connect 论文代码复现
  8. python format方法的格式控制填充_Python中format函数用法
  9. 应用偏最小二乘回归(PLSR)对NIR光谱与样本中RON含量进行定量分析
  10. 如何在cmd下查询mongodb数据库