我们说一下,对于持续增长的数据,如何累加数据
毕竟数据库所有的操作,本质上都会先进行查询操作,只有找到了数据才能对数据进行操作,所以性能的一个瓶颈,就是查询的快慢问题
而查询所依靠的因素,主要是
查询的时间复杂度
数据总量
而和查询的时间复杂度相关的条件,取决于对应的数据结构和算法,但是在MySQL中,这两者是固定的,所以我们唯一能改变的,就是总量了
我们解决海量数据导致存储系统变慢的问题,简单来说就是拆,将所有数据拆分成分片 shard,然后拆出来的每个分片的数据就是可以接受的了
接下来,我们就是如何拆分数据的问题
我们拿一个如何存档历史订单来说明如何提升查询性能,首选的就是归档历史订单
所谓归档,就是拆分数据的策略,简单就是将大量的历史订单移到历史库
毕竟,对于订单表这些热点表,大部分就是访问的最近的数据,订单表中有大量的数据都是不常用的老数据
因为新数据只占数据总量的相对较少的一部分,所以新老数据分开后,新数据就会少很多,查询速度会块很多,老数据虽然和之前比没少多少,但是放在额外的一个表,减少了热点的出现
因为只有查询统计类的功能,会查询历史订单,所以可以简单的按照时间,去查询订单表
大致的流程如下
首先创建一个和订单一样的历史订单表
然后,将数据分批查出来,导入到历史订单表
然后验证能不能走历史订单表,查看代码是否有bug,如果有bug,可以回滚代码,并不影响数据
如果代码无误,删除订单表的冗余数据
然后利用一个脚本,进行批量的导表
接下来,如何删除大量的数据
我们如何从订单表中删除已经迁走的历史数据,直接一口删除,可能因为删除的数据量大,导致阻塞时间过长,所以我们可以分批删除
比如每次删除1000条,进行分批的删除
sql的基本书写如下
delete from orders
where timestamp < SUBDATE(CURDATE(),INTERVAL 3 month)
order by id limit 1000;
执行删除语句的时候,每次删除之间最好可以停顿一秒,直到全部删除
然后更快方便快捷的方式是
只要数据的主键ID是具有自增性的
我们先去timestamp上找出所有符合的记录,然后按照订单ID排序,之后删除之前的1000条数据
我们可以先进行一次查询,找到符合条件的历史订单的最大的订单ID,然后在删除的语句中将删除的依据设置为按照主键删除
这样就避免了回表操作,而且由于Id是有序的,在B+树的有序性,保证了这些Id也是有序的
在删除之后,我们检测一下MySQL占用的磁盘空间,并没有变少,这是因为MySQL只是将其标记可以重新写入,并没有实际的删除
如果需要删除,我们可以执行以下OPTIMIZE TABLE来释放存储空间,这相当于重建一下表,执行过程中会一直锁表,这是需要注意的
除此外,还可以重新新建一个临时表,然后将当前订单的表复制到临时表中,然后修改表明,最后将临时表的名字改为正式表,这相当于手工重新建表
基本SQL如下
— 新建一个临时订单表
create table orders_temp like orders; — 把当前订单复制到临时订单表中 insert into orders_temp select * from orders where timestamp >= SUBDATE(CURDATE(),INTERVAL 3 month); — 修改替换表名 rename table orders to orders_to_be_droppd, orders_temp to orders; — 删除旧表 drop table orders_to_be_dropp |
对于订单这种具有时间属性的表,我们可以利用上卖弄说的拆分方式将旧数据归档,可以起到一个良好的效果,需要注意的是我们重建订单表的方式方法
思考一下:
对于订单库,对比一下分库分表和归档历史订单拆分
相较于直接分库分表,归档历史订单更加的灵活,可以将历史的订单,迁移到查询更快的系统中
直接分库分表,会遇到冷热不均的问题