当单个MySQL表的记录数过多时,增删改查的性能会急剧下降。 您可以参考以下步骤进行优化。

单表优化

除非以后单表数据会继续涨,一开始就不要考虑拆分。 拆分会带来逻辑、部署、运维等方面的各种复杂性。 一般整数值的表都在几千万以下,五百万以下的字符串表问题不大。 事实上,在很多情况下,MySQL单表的性能还有很大的优化空间,甚至可以正常支持千万级以上的数据量:

场地

指数

查询语句

引擎

目前广泛使用的两个引擎MyISAM和InnoDB:

MyISAM

MyISAM引擎是MySQL 5.1及更早版本的默认引擎,其特点是:

InnoDB

InnoDB在MySQL 5.5之后成为默认索引,其特点是:

一般来说,MyISAM适用于SELECT密集型表,而InnoDB适用于INSERT和UPDATE密集型表。

系统调整参数

您可以使用以下工具进行基准测试:

有许多特定的调整参数。 详情请参考官方文档。 以下是一些重要的参数:

升级硬件

Scale up,这个就不多说了,看MySQL是CPU密集型还是I/O密集型,通过增加CPU和内存,使用SSD,MySQL的性能可以得到明显的提升。

读写分离

也是目前常用的优化。 一般来说,不要使用双主或多主来引入很多复杂性。 尝试使用文章中的其他解决方案来提高性能。 同时,目前很多拆分方案也考虑到了读写分离。

缓存

缓存可以发生在这些级别:

缓存可以根据实际情况单级添加,也可以多级组合。 这里着重介绍下服务层的缓存实现。 目前主要有两种方法:

表分区

MySQL在5.1版本引入的分区是一种简单的水平分割。 用户在创建表时需要添加分区参数,对应用程序透明,无需修改代码。

对于用户来说,分区表是一个独立的逻辑表,但底层是由多个物理子表组成的。 实现分区的代码其实是由底层表的一组对象封装的,但是对于SQL层来说,是一个完整的封装了底层的黑盒。 MySQL实现分区的方式也意味着索引也是根据分区的子表定义的,没有全局索引。

用户的SQL语句需要针对分区表进行优化。 分区条件的列应该包含在SQL条件中,这样查询就可以定位到少量的分区上。 否则,将扫描所有分区。 可以通过EXPLAIN PARTITIONS查看某条SQL语句会落在那些分区上,从而进行SQL优化,如下图,5条记录落在两个分区上:

mysql> explain partitions select count(1) from user_partition where id in (1,2,3,4,5);
+----+-------------+----------------+------------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table          | partitions | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+----------------+------------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | user_partition | p1,p4      | range | PRIMARY       | PRIMARY | 8       | NULL |    5 | Using where; Using index |
+----+-------------+----------------+------------+-------+---------------+---------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

分区的好处是:

分区的限制和缺点:

分区类型:

适合分区的场景有:

CREATE TABLE members (
   firstname VARCHAR(25NOT NULL,
   lastname VARCHAR(25NOT NULL,
   username VARCHAR(16NOT NULL,
   email VARCHAR(35),
   joined DATE NOT NULL
)
PARTITION BY RANGEYEAR(joined) ) (
   PARTITION p0 VALUES LESS THAN (1960),
   PARTITION p1 VALUES LESS THAN (1970),
   PARTITION p2 VALUES LESS THAN (1980),
   PARTITION p3 VALUES LESS THAN (1990),
   PARTITION p4 VALUES LESS THAN MAXVALUE
);

如果数据有明显的热点,而除了这部分数据之外其他数据很少被访问,那么可以将热点数据放在一个单独的分区中,让这个分区中的数据有机会缓存​​到内存中,且仅在查询时访问 高效利用索引和缓存的小型分区表。

另外,MySQL有一个早期简单的分区实现——merge table,限制较多,缺乏优化。 不推荐使用,应该换成新的分区机制。

垂直分割

垂直数据库拆分是基于数据库中数据表的相关性。 比如一个数据库中既有用户数据又有订单数据,那么垂直拆分可以将用户数据放入用户数据库,将订单数据放入订单库。 垂直拆分表是一种垂直拆分数据表的方法。 将一个大的多字段表按常用字段和不使用字段拆分是很常见的。 每个表的数据记录条数一般是一样的,只是字段不一样,用的是主键关联。

比如原来的用户表是:

垂直拆分后是:

垂直拆分的优点是:

弱点是:

水平分割

概述

水平拆分就是通过一定的策略,将数据分段存储。 分库中有分表和分库两部分。 每一条数据都会分布到不同的MySQL表或者库中,达到分布式的效果,可以支持非常大的数据量。 前面的表分区本质上是库中一个特殊的子表。

数据库中的分表简单的解决了单表数据量过大的问题。 由于表中的数据并没有分布到不同的机器上,所以对减轻MySQL服务器的压力作用不大。 大家还在同一台物理机上争IO、CPU、网络,这个必须要通过分库来解决。

如果将之前垂直拆分的用户表水平拆分,则结果为:

实际情况中,往往是垂直拆分和水平拆分的组合mysql一张表能存多少条数据,即Users_A_M和Users_N_Z拆分成Users和UserExtras,所以一共有四张表。

水平拆分的优点是:

弱点是:

分片原则

这里特别强调sharding规则的选择。 如果某张表中的数据具有明显的时间特征,比如订单、交易记录等,通常更适合按时间段进行分片。 因为数据具有时效性,所以我们经常关注它最近的数据。 查询条件通常使用时间字段进行过滤。 更好的解决方案是对当前活跃的数据使用一个相对较短的时间跨度mysql一张表能存多少条数据,而对历史数据使用一个相对较长的跨度。 跨度存储。

一般来说,分片的选择取决于最频繁查询SQL的条件,因为没有任何Where语句的查询SQL会遍历所有分片,性能相对最差,所以这样的SQL越多,影响越大对系统的影响越大,所以要尽量避免这条SQL的产生。

解决方案

由于水平拆分涉及的逻辑复杂,目前已经有很多成熟的解决方案。 这些方案分为两大类:客户端架构和代理架构。

客户端架构

通过修改数据访问层,如JDBC、Data Source、MyBatis,通过配置管理多个数据源,直接连接数据库,在模块中完成数据的分片和整合,一般以Jar的形式呈现包裹。

这是客户端架构的示例:

mysql随机取5条数据_mysql一张表能存多少条数据_mysql取出倒数n条数据

可以看出,分片的实现是和应用服务器在一起的,是通过修改Spring JDBC层来实现的。

客户端架构的优点是:

弱点是:

代理架构

通过独立的中间件统一管理所有数据源和数据分片整合,后端数据库集群对前端应用透明,需要代理组件独立部署和运维。

以下是代理架构的示例:

mysql随机取5条数据_mysql取出倒数n条数据_mysql一张表能存多少条数据

为了分流和防止单点,代理组件一般以集群的形式存在,可能需要Zookeeper等服务组件进行管理。

代理架构的优点是:

弱点是:

程序比较

mysql一张表能存多少条数据_mysql随机取5条数据_mysql取出倒数n条数据

mysql取出倒数n条数据_mysql一张表能存多少条数据_mysql随机取5条数据

这么多选择,如何选择? 可以从以下几个方面考虑:

确定是使用代理还是客户端架构。 中小型或者比较简单的场景倾向于选择客户端架构,复杂场景或者大型系统倾向于选择代理架构;

是否满足特定功能,比如需要跨节点ORDER BY,则优先支持该功能;

一年内没有更新的产品不予考虑,说明发展停滞,甚至没有维护和技术支持;

最好按照大公司->社区->小公司->个人的顺序进行选择;

选择口碑好的,比如github stars、用户数量和质量、用户反馈等;

开源是首选,往往有特殊需求的项目可能需要改源码。

基于以上思路,推荐以下方案:

兼容MySQL和水平扩展数据库

还有一些兼容MySQL协议的开源数据库,比如:

但其工业品质与MySQL仍有差距,需要较大的运维投入。 如果想把原来的MySQL迁移到新的可以横向扩展的数据库,可以考虑一些云数据库:

无SQL

MySQL 上的分片是带枷锁的舞蹈。 其实很多大表对MySQL等RDBMS的需求并不大,不需要ACID。 可以考虑将这些表迁移到NoSQL,彻底解决横向扩展的问题。 ,例如: