前言

千万级大表如何优化,这是一个很有技术含量的问题,通常我们的直觉思维都会跳转到拆分或者数据分区。除此之外,还有其他的思路和解决方案。根据本人多年的工作经验,做了如下总结。

方案

"千万级大表优化"这句话有3个关键字: 千万级,大表和优化。接下来将就这3个关键字展开讨论。

数据量:千万级

随着业务的发展,应用需要处理的数据量也是动态变化的。这也意味着要带着一种动态思维来系统的数据量,从而对于不同的场景我们应该有不同的处理策略。

①数据量为千万级,可能达到亿级或者更高

这类数据通常是数据流水,日志,关注和聊天记录,里面的数据随着时间的增长而逐渐增多,可以达到亿级别。

②数据量为千万级,增长可以预期

如果数据量相对稳定,通常存储偏向于状态的数据,比如用户,商品和订单,这类信息在表中都有相应的一行或者多行数据记录,随着业务的增长,增长量级相对是比较稳定的。

③数据量为千万级,冗余数据居多

这种情况一般出现在配置或者跟时间轴相关的业务表中。大部分数据属于无效数据或过期数据。

数据量是一个粗略的认识,我们需要对数据的结构和内容做更进一步的分析。

对象:数据表

数据根据不同的操作类型和业务特征可以分为如下几类:

①流水型数据

流水型数据是无状态的,只存在插入和查询两种操作。比如交易流水、支付流水,只要能插入新单据就能完成业务,特点是后面的数据不依赖前面的数据,所有的数据按时间流水进入数据库,数据热点只存在于最近的时间段。

②状态型数据

状态型数据是有状态的,多笔业务之间依赖于有状态的数据,而且要保证该数据的准确性,比如充值时必须要拿到原来的余额,才能支付成功。这类数据的操作必须依赖事务机制来保证一致性。存在插入,更新和查询等多种操作。

③配置型数据

此类型数据数据量较小,而且结构简单,一般为静态数据,变化频率很低。

针对不同的数据存储特性和业务特点来指定不同的业务策略。对此我们把常见的优化思路梳理出来,尤其是里面的核心思想,也是我们整个优化设计的框架,而难度决定了我们做这件事情的动力和风险。

数据量增长情况 数据表类型 业务特点 优化核心思想 难度
增长比较平均 状态表 OLTP业务方向 进行容量规划,保证存储2年内的业务数据尽量保证稳定,读需求水平扩展 ★★★★
增长比较迅速 流水表 OLTP业务历史记录 业务拆分,使用海量存储机制 ★★★★
OLAP业务统计数据 使用大数据存储机制
增长比较缓慢 配置表 通用业务 分布式配置中心,个性化存储  

目标:优化

在这个阶段,我们要说优化的方案了,我们要支撑的表数据量是千万级别,相对来说是比较大了,DBA 要维护的表肯定不止一张,如何能够更好的管理,同时在业务发展中能够支撑扩展,同时保证性能,这是摆在我们面前的几大挑战。根据我多年的工作经验整体分为五个部分:

规范设计

业务层优化

架构层优化

规范设计

配置规范:

MySQL 数据库默认使用 InnoDB 存储引擎。

保证字符集设置统一,MySQL 数据库相关系统、数据库、表的字符集都使用 UTF8MB4,应用程序连接、展示等可以设置字符集的地方也都统一设置为 UTF8MB4 字符集。

注:UTF8 格式是存储不了表情类数据,需要使用 UTF8MB4,可在 MySQL 字符集里面设置。在 8.0 中已经默认为 UTF8MB4,可以根据公司的业务情况进行统一或者定制化设置。

MySQL 数据库的事务隔离级别默认为 RR(Repeatable-Read),建议初始化时统一设置为 RC(Read-Committed),对于 OLTP 业务更适合。

数据库中的表要合理规划,控制单表数据量,对于 MySQL 数据库来说,建议单表记录数控制在 2000W 以内。将历史数据同步到大数据存储

MySQL 实例下,数据库、表数量尽可能少;数据库一般不超过 50 个,每个数据库下,数据表数量一般不超过 500 个(包括分区表)。

建表规范:

InnoDB 禁止使用外键约束,可以通过程序层面保证。

存储精确浮点数必须使用 DECIMAL 替代 FLOAT 和 DOUBLE。

整型定义中无需定义显示宽度,比如:使用 INT,而不是 INT(4)。

不建议使用 ENUM 类型,可使用 TINYINT 来代替。

尽可能不使用 TEXT、BLOB 类型,如果必须使用,建议将过大字段或是不常用的描述型较大字段拆分到其他表中;另外,禁止用数据库存储图片或文件。

存储年时使用 YEAR(4),不使用 YEAR(2)。

建议字段定义为 NOT NULL。字段为NULL会导致索引失效。

建议 DBA 提供 SQL 审核工具,建表规范性需要通过审核工具审核后。

命名规范:

库、表、字段全部采用小写。

库名、表名、字段名、索引名称均使用小写字母,并以“_”分割。

库名、表名、字段名建议不超过 12 个字符。(库名、表名、字段名支持最多 64 个字符,但为了统一规范、易于辨识以及减少传输量,统一不超过 12 字符)

库名、表名、字段名见名知意,不需要添加注释。

对于对象命名规范的一个简要总结如下表所示,供参考:

命名列表

索引规范:

索引建议命名规则:idx_col1_col2[_colN]、uniq_col1_col2[_colN](如果字段过长建议采用缩写)。

索引中的字段数建议不超过 5 个。

单张表的索引个数控制在 5 个以内。

InnoDB 表一般都建议有主键列,尤其在高可用集群方案中是作为必须项的。

建立复合索引时,优先将选择性高的字段放在前面。

UPDATE、DELETE 语句需要根据 WHERE 条件添加索引。

不建议使用 % 前缀模糊查询,例如 LIKE “%weibo”,无法用到索引,会导致全表扫描。

合理利用覆盖索引,例如:SELECT email,uid FROM user_email WHERE uid=xx,如果 uid 不是主键,可以创建覆盖索引 idx_uid_email(uid,email)来提高查询效率。

避免在索引字段上使用函数,否则会导致查询时索引失效。

确认索引是否需要变更时要联系 DBA。

应用规范:

避免使用存储过程、触发器、自定义函数等,容易将业务逻辑和DB耦合在一起,后期做分布式方案时会成为瓶颈。

考虑使用 UNION ALL,减少使用 UNION,因为 UNION ALL 不去重,而少了排序操作,速度相对比 UNION 要快,如果没有去重的需求,优先使用 UNION ALL。

考虑使用 limit N,少用 limit M,N,特别是大表或 M 比较大的时候。

减少或避免排序,如:group by 语句中如果不需要排序,可以增加 order by null。

统计表中记录数时使用 COUNT(*),而不是 COUNT(primary_key) 和 COUNT(1)。

InnoDB 表避免使用 COUNT(*) 操作,计数统计实时要求较强可以使用 Memcache 或者 Redis,非实时统计可以使用单独统计表,定时更新。

做字段变更操作(modify column/change column)的时候必须加上原有的注释属性,否则修改后,注释会丢失。

使用 prepared statement 可以提高性能并且避免 SQL 注入。

SQL 语句中 IN 包含的值不应过多。

UPDATE、DELETE 语句一定要有明确的 WHERE 条件。

WHERE 条件中的字段值需要符合该字段的数据类型,避免 MySQL 进行隐式类型转化。在隐式转换的时候,容易导致s。

SELECT、INSERT 语句必须显式的指明字段名称,禁止使用 SELECT * 或是 INSERT INTO table_name values()。

INSERT 语句使用 batch 提交(INSERT INTO table_name VALUES(),(),()……),values 的个数不应过多。

业务层优化

业务层优化应该是收益最高的优化方式了,而且对于业务层完全可见,主要有业务拆分,数据拆分和两类常见的优化场景(读多写少,读少写多)。

①业务拆分

业务拆分分为如下两个方面:

将混合业务拆分为独立业务

将状态和历史数据分离

业务拆分其实是把一个混合的业务剥离成为更加清晰的独立业务,这样业务 1,业务 2......独立的业务使得业务总量依旧很大,但是每个部分都是相对独立的,可靠性依然有保证。

例如:我们有一张表 Account,假设用户余额为 100。

我们需要在发生数据变更后,能够追溯数据变更的历史信息,如果对账户更新状态数据,增加 100 的余额,这样余额为 200。

这个过程可能对应一条 update 语句,一条 insert 语句。对此我们可以改造为两个不同的数据源,account 和 account_hist。

在 account_hist 中就会是两条 insert 记录,如下:

而在 account 中则是一条 update 语句,如下:

这也是一种很基础的冷热分离,可以大大减少维护的复杂度,提高业务响应效率。

②数据拆分

按照日期拆分:这种使用方式比较普遍,尤其是按照日期维度的拆分。其实在程序层面的改动很小,但是扩展性方面的收益很大。

数据按照日期维度拆分,如 order_20191021。

数据按照周月为维度拆分,如 test_201910。

数据按照季度,年维度拆分,如 test_2019。

采用分区模式:分区模式也是常见的使用方式,采用 hash,range 等方式很多。

在 MySQL 中我是不大建议使用分区表的使用方式,因为随着存储容量的增长,数据虽然做了垂直拆分,但是归根结底,数据其实难以实现水平扩展,在 MySQL 中是有更好的扩展方式。

③读多写少优化场景

采用缓存,采用 Redis 技术,将读请求打在缓存层面,这样可以大大降低 MySQL 层面的热点数据查询压力。

④读少写多优化场景

读少写多优化场景,可以采用三步走:

采用异步提交模式,异步对于应用层来说最直观的就是性能的提升,产生最少的同步等待。

使用队列技术,大量的写请求可以通过队列的方式来进行扩展,实现批量的数据写入。

举个例子:对于评论类业务数据,相比于金额来说属于业务优先级略低的场景。如果数据更新过于频繁,可以适度调整数据更新的范围(比如从原来的每分钟调整为 10 分钟)来减少更新的频率。对于业务指标,比如更新频率细节信息,可以根据具体业务场景来讨论决定。

架构层优化

架构层优化是业务框架的基础设施优化,我们需要根据业务场景在架构层面引入新的解决方案,达到事半功倍的效果。

①系统水平扩展场景

采用中间件技术,可以实现数据分片路由和读写分离。常见的中间件有ShardingSphere,zebra,Atlas 等。根据实现方案的不同分为客户端代理和服务端代理。

数据分片路由主要指的是分库分表。通过指定对应数据记录的分片键将数据路由到不同的数据库表,实现数据库容量的水平扩展。

采用读写分离技术是对读需求的扩展,更侧重于状态表,在允许一定延迟的情况下,可以采用多副本的模式实现读需求的水平扩展。

②兼顾 OLTP+OLAP 的业务场景

可以采用 NewSQL,优先兼容 MySQL 协议的 HTAP 技术栈,如 TiDB。

③离线统计的业务场景

有几类方案可供选择:

采用 NoSQL 体系,主要有三类,一类是适合兼容 MySQL 协议的数据仓库体系,常见的有 Infobright 或者 ColumnStore,另外一类是基于列式存储,属于异构方向,如 HBase 技术。还有一类是基于文档的MongoDB技术。

采用数仓体系,基于 MPP 架构,如使用 Greenplum 统计,如 T+1 统计。

MySQL千万级数据量优化方案相关推荐

  1. mysql千万级数据量根据索引优化查询速度

    (一)索引的作用 索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询sql执行往往需要几十秒甚至更多,5秒以上就已经 ...

  2. MYSQL千万级数据量的优化方法积累

    为什么80%的码农都做不了架构师?>>>    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 whe ...

  3. MySQL亿级数据数据库优化方案测试-银行交易流水记录的查询

    对MySQL的性能和亿级数据的处理方法思考,以及分库分表到底该如何做,在什么场景比较合适? 比如银行交易流水记录的查询 限盐少许,上实际实验过程,以下是在实验的过程中做一些操作,以及踩过的一些坑,我觉 ...

  4. 记一次mysql千万级数据量(上千亿都行)的处理(java)

    1.前言 项目一个表经历着一天3W条数据入表,一年就有1000W,单表随着数据的增多,查询都会逐渐卡,加了索引依旧出现查询卡 2.经过 因为我用的是java,起初解决方案是用[shardingsphe ...

  5. 百万级数据量,千万级数据量是多少,海量数据的优化方案

    百万级数据量,千万级数据量是多少? 这里的百万级,千万级,针对数据库,指的是表的数据条数.有时也指并发事务量. 海量数据的优化方案 Note:    具体优化要结合自身的业务特性 百万级: 这个数据量 ...

  6. mysql千万级数据查询select、插入insert慢 可能原因总结

    mysql千万级数据查询select.插入insert慢 可能原因总结 表连表查询 并 insert ,insert into -select -from- insert into T1(XX,XX) ...

  7. MySQL千万级大表优化解决方案

    MySQL千万级大表优化解决方案 参考文章: (1)MySQL千万级大表优化解决方案 (2)https://www.cnblogs.com/yliucnblogs/p/10096530.html 备忘 ...

  8. MySQL深度分页的问题及优化方案:千万级数据量如何快速分页

    前言 后端开发中为了防止一次性加载太多数据导致内存.磁盘IO都开销过大,经常需要分页展示,这个时候就需要用到MySQL的LIMIT关键字.但你以为LIMIT分页就万事大吉了么,Too young,to ...

  9. MySQL千万级数据优化方案

    简介 ↓↓↓处理千万级数据的MySQL数据库,可以采取以下优化措施↓↓↓ 使用索引:确保对经常用于查询和排序的字段添加索引.不要在查询中使用SELECT *,而是明确指定需要的字段. 分区表:如果表中 ...

最新文章

  1. javascript晚绑定_JavaScript的应用,调用和绑定通过托管野餐来解释
  2. solr4.5分组查询、统计功能介绍
  3. [20180102]11g的V$SORT_USAGE视图.txt
  4. vba执行linux命令,从VBA中的shell命令捕获输出值?
  5. 5.7.21mysql数据库_【数据库】mysql5.7.21 winx64安装配置图文分享
  6. org.springframework.uti包下的StringUtils的使用和org.apache.commons.lang包下StringUtils的使用
  7. 从0开始学习自动化测试框架cypress(五)案例
  8. SAP License:SAP顾问是如何炼成的——SAP顾问的定义
  9. 如何在《救赎之路》中使用CPU粒子效果
  10. html 图片分散,纯js和CSS3分散式宝丽来图片画廊
  11. 前端技术—CSS常用代码大全
  12. 中标麒麟linux系统安装打印机_国产中标麒麟操作系统的打印机安装
  13. 未来杯总结1--cuda8.0+cuDnnv6+anavonda+tensorflow-gpu+keras+ubuntu16.04
  14. obs 推流编码在哪设置_直播工具OBS推流配置操作指引
  15. 论文翻译:2021_Performance optimizations on deep noise suppression models
  16. 了解uni-app只需这一篇就足够了
  17. bubu PC端的应用商店1 -架构
  18. spring BeanPostProcessor使用场景
  19. php花曲线,ps钢笔工具怎么画曲线
  20. uni-app在华为应用市场上架审核无法通过,涉及个人信息:IMEI用户数据收集问题

热门文章

  1. 2023最新高频前端面试题总结(附答案)
  2. 计算机毕业设计Java个人理财系统(源码+系统+mysql数据库+lW文档)
  3. 浅谈js下的发布订阅模式(观察者模式)
  4. 匈牙利算法python代码实现以及原理图解
  5. vbs执行相应的bat文件
  6. 黑马程序员—对话框Dialog小例子
  7. 感知系统性能评估分析解决方案
  8. wxc-cell使用
  9. 计算机管理没有本地用户和组控制面板,win10管理没有本地用户和组怎么办_win10电脑管理没有本地用户和组解决方法...
  10. windows2008 没有本地用户和组