场景——MYSQL

一、MYSQL 亿级表新增字段怎么弄?

优先方案:MySQL8.0 Instant 算法(秒级完成)。

适用条件:

MySQL版本≥8.0.12

新增字段位于所有列的最后(不支持字段中间插入)

表非压缩格式(ROW FORMAT≠COMPRESSED)

无全文索引/FTS表

2 其他方案(Mysql版本低于8):

  • pt-OSC工具
  • 新增一张同结构的临时表,加新字段,再把亿级数据导过去。最后改名替换原表(Rename table A to A_old, A_new to A;)

 

二、分库分表后查询性能暴跌怎么办?

场景:对订单表拆分,通过 user_id % 1024 将数据分散到 1024 个分片,现在要根据 order_id 查询。

卡点:

  • 当 WHERE 条件携带 user_id 时,可精准定位分片(如 user_id=101 → 分片 101%1024=101);
  • 当仅按 order_id 查询时,需遍历全部 1024 个分片,导致查询性能暴跌;

方案:

    • 冗余全表法:存储两份数据 → 分别按 user_id 和 order_id 分片;
        缺点:存储翻倍、数据一致性难解决;
    • 索引表法:只创建一个包含 user_id 和 order_id 的索引表,在插入订单时再插入一条数据到索引表中,查询时先去索引表根据 order_id 获取 user_id,再去对应分片查询;
        缺点:查询延时(要先查索引表)、随着数据量变大,索引表可能也要分片;
    • 基因分片法:将分片路由信息嵌入业务ID,通过在雪花算法生成的ID中植入“分片基因”,使任何ID都自带位置信息;(order_id 中包含 user_id 的基因

 

三、MYSQL 海量数据的分页查询优化,如果主键是分布式ID?

场景:使用 select ... limit offset,size,分页在大数据量下存在性能瓶颈。

分析:

  • 数据偏移(Offset过大):MySQL需扫描前 offset 条记录并丢弃,(如 LIMIT 10000,10 需扫描 10010 行),导致 I/0 和CPU资源浪费;
  • 内存占用过高:全结果集加载到内存再截取,可能触发OOM(OutofMemory);
  • 回表开销:若未覆盖索引,需回表查询完整数据,产生随机I/O;
  • COUNT(*)效率低:统计总数需全表扫描,加剧性能问题;

单机方案:

1 游标分页:

  • 原理:记录上一页最后一条记录的ID(或时间戳),基于有序字段定位下一页起始位置;
  • 要求:排序字段需唯一旦连续(如自增主键或时间戳),必须建立索引;

2 延迟关联:

  • 原理:先通过覆盖索引获取主键,再关联原表减少回表次数;
  • 场景:非主键排序,深分页;

3 覆盖索引:

  • 原理:索引包含查询所需所有字段,无需回表;
  • 要求:查询字段必须全在索引中;

4 主键范围分页:

  • 原理:利用主键连续性分块查询(需ID连续无空洞);
  • 缺点:数据删除影响ID连续性;

5 业务层优化:

  • 缓存总数:避免重复执行cOUNT(*);
  • 用 Redis 缓存总行数限制页数:如百度仅展示79页,避免深分页;
  • 预加载策略:热门数据预加载到缓存;

分布式方案:

1 基于分布式ID的范围查询:

  • 场景:排序字段为分布式ID(如Snowflake生成的主键);
  • 优势:各分片并行查询,无需全局聚合;

2 全局二级索引:

  • 原理:在分布式数据库(如PolarDB-X)中创建跨分片索引,统一排序字段;

3 ES辅助查询: 

  • 流程:
    • 写数据时同步到 ES (含主键和排序字段);
    • 分页查询由 ES 返回主键列表;
    • 用主键批量查询数据库获取明细; 
  • 优势:ES擅长排序分页; 

4 分页中间件:

  • 工具:ShardingSphere支持跨库分页路由;

 

四、如何优化Mysql频繁全表扫描的查询性能?

原因:

  • 消耗大量磁盘I/0:对于大表来说,读取整张表的数据可能需要大量的磁盘读取操作;
  • 占用内存资源:即使MYSQL采用“边读边发”的策略,但在某些情况下,仍需要将部分或全部结果集保存到内存中;
  • 降低系统响应速度:全表扫描会导致查询响应时间变长,进而影响用户体验和其他业务的正常运行;

解决方案:

索引优化:让数据查找更高效
  • 使用聚合索引:将单键索引改为聚合索引,覆盖搜索字段
  • 避免索引失效:如不使用OR,改为 UNION 或 UNION ALL 替代
分区表:减少扫描范围
  • 使用聚合索引:将单键索引改为聚合索引,覆盖搜索字段
  • 避免索引失效:如不使用OR,改为 UNION 或 UNION ALL 替代
查询优化:减少查询开销
  • 减少查询:避免 select *,只返回必要字段
  • 分页查询:limit 和 offset
  • 缓存结果:高频数据 redis 存储
数据归档与清理:减少数据膨胀
  • 历史数据迁移
  • 定期清理无用数据
硬件与配置优化:提升底层性能
  • 增加内存
  • 调整配置参数
  • 使用固态硬盘
架构优化:分布式与负载均衡
  • 读写分离
  • 分库分表

 

五、干万级大表如何快速删除大量数据

1. 分批次删除(最通用)

  • 做法:循环删除,每次 1000-10000 条,加LIMIT和短暂停顿(如 0.1 秒)。 
  • 优点:避免大事务,控制锁表时间和日志量。
  • 注意:删除条件需加索引,分批大小根据数据库负载调整。

2. 分区表删除(提前设计)

  • 做法:按时间 / 范围分区,直接删除分区(秒级)。 
  • 优点:不逐行删除,适合日志表等历史数据清理。
  • 前提:表需提前设计为分区表。

3. TRUNCATE TABLE(删全表)

  • 做法:TRUNCATE TABLE Table;
  • 优点:不生成日志,速度极快,释放空间。
  • 限制:无法带条件,会重置自增 ID,谨慎用于有下游同步(如 binlog)的场景。

4. 新表迁移法(保留少量数据)

  • 步骤:新建表存保留数据→删旧表→重命名新表。 
  • 适用:删除 90% 以上数据(如保留近 30 天数据)。

5. 工具辅助(如 pt-archiver)

  • MySQL 工具:自动分批、限速、记录日志,适合千万级以上数据。

 

六、 

posted @ 2025-08-08 15:41  幻月hah  阅读(13)  评论(0)    收藏  举报