这里的时序数据泛指一切随时间推移而不断增长的数据,比如通话记录、银行交易记录等。
对于数据库来讲,时序数据并没有什么特殊性,可以和普通数据一样放在数据表中。不过,因为不断增长,积累时间较长后,这种数据的量常常都会很大。一个物理表的数据量太大时,就会影响查询和计算的性能。
现代数据库一般都提供有表分区(PARTITION)的机制,就是把一个大表纵向(按行)分成若干区段,分区规则由数据库管理员来设置,对应用程序员来讲是透明的,可以和不分区的表一样访问,数据库会自动根据查询条件决定读取哪些分区的数据,这样的接口体验非常好。
不过,在实战中,分区表的效果在某些场景下并不好,而且使用时也有些约束条件,并不总好用且能用的。结果,在实际业务中,我们常常会看到对于这种大数据采用手工物理分表的方案。
所谓物理分表,就是人为将一个大表分成若干较小的物理数据表。因为时序数据的结构中一定会有一个字段来表示事件发生的时刻,而事件发生的数量一般来讲也会按时间段相对平均分布(大多数情况会缓慢增长,但讨论时可以忽略),所以最常用的方案就是按时间段来做分表,比如一个月数据对应一个分表,这种方式在金融、电信行业比较普遍。
物理分表并不是数据库自动支持的方案,不能对应用程序做到透明,需要应用程序自己处理。在查询数据时一般都会有时间段参数,应用程序可以根据这个参数计算出该查询涉及哪些分表,然后将这些分表UNION起来拼到SQL语句的FROM后面。查询不涉及的时间段对应的分表不会被拼进来,这样就可以有效减少数据遍历的范围,从而提高性能。
这个方案在单个数据库时没啥毛病,但是不是能推广到多个数据库的情况呢?
数据量再大下去,一个数据库也无法承受了,而某些场景下又不允许我们上一套分布式数据库系统,毕竟分布式数据库是个沉重的工程,不仅造价高,而且维护管理都要复杂不少。这时候,我们可以摆多个数据库分别存储数据,类似物理分表的方案,也按时间段把数据分拆到各个数据库中,比如一年数据放入一个数据库中(一般来讲多个库会部署到多台机器上),这样就能分摊查询压力了。