MYSQL大表问题

603 阅读5分钟

大表批量删除问题

删除一条记录,首先锁住这条记录数据原有的被废弃记录头发生变化,主要是打上了删除标记。也就是原有的数据 deleted_flag 变成 1,代表数据被删除。但是数据没有被清空,在新一行数据大小小于这一行的时候,可能会占用这一行。这样其实就是存储碎片

之后,相关数据的索引需要更新,清除这些数据。并且,会产生对应的 binlog 与 redolog 日志。 如果 delete 的数据是大量的数据,则会:

  • 如果不加 limit 则会由于需要更新大量数据,从而索引失效变成全扫描导致锁表,同时由于修改大量的索引,产生大量的日志,导致这个更新会有很长时间,锁表锁很长时间,期间这个表无法处理线上业务。
  • 由于产生了大量 binlog 导致主从同步压力变大
  • 由于标记删除产生了大量的存储碎片。由于 MySQL 是按页加载数据,这些存储碎片不仅大量增加了随机读取的次数,并且让页命中率降低,导致页交换增多
  • 由于产生了大量日志,我们可以看到这张表的占用空间大大增高。

大表批量删除对查询的影响

  • 当新的会话执行SQL时,如果扫描区间内有大量被标记删除的记录,会导致SQL执行效率低。例如where c1 = 1,有10晚match的记录时,其中扫描方向90%的记录都被标记为已删除,但还没有purge就会效率低(已经提交的事务只有在RR隔离级别下会出现这个情况)

大数据量表如何新增字段

  • 基础方法:几十万数据一般可以直接添加
  • 临时表:复制临时表,加上新增字段,然后拷贝过去

大数据量limit问题

limit页数特别大的时候回影响性能,可以先选好id范围,大于某个id再用limit

快速批量插入

  • buffer_size 空间 和 max_allowed_packet语句运行长度设最大
  • insert into table (v1,v2,v3) values (a,b,c),(a,b,c),(a,b,c)

使用mybatis批量插入的话,循环插入最不可取,可以使用原生拼接,插入效率最高,但是需要调整和预估好SQL限制,不然容易程序报错

大表性能问题

  • 建表字段小
  • 索引(不走索引的查询会很慢)
  • 归档数据、冷热分离
  • 读写分离
  • 分库分表

碎片化空间处理

  • mysql check可以找出表空间中超过10M的最大的10个表
  • 也可以通过data_free进行判断碎片化空间的大小
  • alter table xxx force 可以对表空间进行整理(随机IO,比较耗时,也会阻塞表上正常的DML运行)
  • 复制一个新表,拷贝过去

PGsql和Mysql的区别

PG的优势:

  • PG的主从复制属于物理复制,相比mysql通过binlog的逻辑复制,数据的一致性更加可靠,复制性能更高,对主机性能影响也更小。
  • 优化器的功能更加完善,支持索引的类型更多,复杂查询能力更强
  • 功能集更出色
  • PG主表采用堆表存放,比Mysql的索引组织表,支持更大的数据量

Mysql的优势:

  • Mysql的优化器先对简答,但也更适合简单的查询操作,因为在并发高的项目里,对数据库的查询上很少会有复杂查询
  • 存储引擎插件化,使其更灵活,应用场景更广泛
  • 索引组织表,这种查询方式更适合主键匹配查询,有聚簇索引

分库分表

水平分表方案:时间维度分表、用户id一致性hash取模

sharding-sphere(sharding-jdbc)

是一个jar包,使用时需要修改代码

优点:

  • 轻量,范围更容易界定,只是 JDBC 增强,不包括HA、事务以及数据库元数据管理
  • 无运维成本,无需关注中间件本身的高可用
  • 性能高,JDBC直连数据库,无需二次转发
  • 可支持各种基于JDBC协议的数据库,如:MySQL,Oralce,SQLServer

缺点:

  • 不够通用,仅支持某一种语言。
  • 版本升级困难,如果中间件有问题,使用该中间件的所有服务都需要升级。

分布式全局唯一ID

雪花算法

使用一个64bit的long型数字作为全局唯一id。

  • 1bit:0,无意义
  • 41bit:时间戳
  • 5bit:机房id
  • 5bit:机器id
  • 12bit:序号,某机房某机器上这一毫秒内同时生成的id的序号

UUID/GUID

规范定义了包括网卡MAC地址、时间戳、Namespace、随机数、时序等元素,UUID的复杂性保证了它的唯一,但是这个唯一性是有限的,只在特定范围内保证。

分片规则和策略

  • 随机分片hash
  • 连续分片

基因法

跨分片技术问题

跨分片的排序分页

跨分片的函数处理

跨分片join:(全局表、字段冗余来解决)

TDDL

mycat

在中间件层,是一个第三方应用,不需要改代码,所有的jdbc请求都要先交给mycat,再转发给真实的服务器。

  • 优点:通用,改造少,多语言支持
  • 缺点:需要二次转发,有性能损失,有运维成本

读写分离数据一致性问题

数据同步写入:主从同步改成同步方案,但会影响性能

读数据从主库读:直接改成从主库读

****缓存路由:写库的时候把key存到缓存中,存较短时间(经验值),读的时候先去缓存判断是否存在key,存在则去主库读,否则去从库读。

缓存存储:请求去存数据库的时候,同时缓存数据,后续业务先从缓存中拿,会有缓存和数据库一致问题

参考:

大表批量删除问题

数据库delete的影响