在“量化投资剖析”场景中,零碎须要从数据接口、网络上等各个中央获取证券的信息,其中往往以“实时的价格变动信息”为次要数据,而后再对这些数据进行实时的剖析与存储,供盘中和盘后应用。某企业遇到的问题如下:“咱们要对 500 个证券种类进行监控,在收盘时,每 5 秒会更新一次价格数据。这样算下来的话,每个证券种类一天就会产生 2880 条记录,如果是 500 个的话,就会有 144 万条数据。而这,还仅仅是一天中产生的数据。如果应用 MySQL 数据库,咱们该如何设计数据库和表,来承载这样的数据量呢?”
援用
从上述场景及问题登程,咱们邀请到 TDengine 解决方案架构师进行回复,并产出本篇文章。
144 万条的数据量对于关系型数据库来说,的确是个有肯定规模的日增量。但从场景上看,上述问题场景还算不上「量化剖析投资」的外围,只能称之为数据抓取的场景。其中抓取对象为「证券」,规模 N = 500,抓取工夫距离 T = 5s。咱们能够假如每次抓取的数据有:
{scrawlTime: '2023-01-01 00:00:00'stock_code: 12345,price: 12.00,volumn: 134,bid_price_1: 12.01,bid_pridce_2: 12.02}
如果要与常见的场景进行类比,能够应用 IT 服务器的运维监控比照。数据如下:
{timestamp: '2023-01-01 00:00:00'ip: '172.16.8.1',cpu_usage: 0.81,memory_usage: 0.23}
通过上述比照咱们能够看到,两种场景很类似。因而,从概念上讲,上述问题场景下的监控数据能够演绎为 metric —— 测量值,并且是随工夫变动的。这是很典型的时序数据,问题场景就是一种经典的时序数据存储场景。
基于 MySQL 的建模
如果企业要用 MySQL 的话,其实外围要思考的问题应该是:
- 如何保障可能及时写入:500 rows/5s = 100 rows/s(但这个根本不是问题)。
-
如何保障可能疾速查出?从 IT 运维看,常见的查问包含:
-
查问单个证券:
- 基于工夫范畴查问:ts in [startTs, endTs)
- 基于监控值的过滤:WHERE bid_price_1 >= 10.00;
- 最新值查问:ORDER BY ts DESC LIMIT 1
- 查问多个证券:在单个证券雷同的状况下,只须要更快地返回,能在 1 个查问里返回更好。
-
基于工夫的计算:
- 滑动窗口:如 5 日均线图
- 状态窗口:依据成交量分段统计
- 。。。
-
基于以上的查问场景,咱们能够抉择两大路线:
-
N 个证券,每 K 个证券,放在 1 个 table 中
- K = 1 时,相当于 1 个证券 1 个 table
- K = N 时,相当于用 1 个 table 寄存所有数据
假如你应用 InnoDB 引擎(innodb_百度百科),不管怎么选,为了性能你都会建索引。而 InnoDB 的索引应用 B-Tree 构造,这个数据结构在 Rows > 2000w(经验值)时,数据写入会因为索引的保护成本上升而降落,查问性能也一样。只是 K = 1 的时候,这个问题才没那么显著:
2000w / 2880/day = 6944 days = 19 years
也就是说 1 个证券 1 个 table 的时候,寄存 19 个天然年数据时,才会显著感知到。
当然,咱们对这个问题有另外一种解决办法:依照工夫(个别以天为单位)在进行分表(或分库):
N 个 证券,每 K 个证券,每 D 天 放在 1 个 table
-
当 K = 1 时
- D = 1,相当于 1 个证券 1 天 1 个 table。1 年下来有 N/K x 365 = 182,500 个 table。
- D = 30,相当于 1 个证券 30 天 1 个 table。1 年下来 有 6083 个 table。
- D = INF,相当于 1 个证券 1 个 table。
-
K = N 时,相当于用 1 个 table 寄存所有数据
- D = 1,相当于所有证券 1 天 1 个 table。1 年下来 365 个 table。
- D = 30,相当于 30 天 1 个 table。1 年下来 12 个 table。
- D = INF,相当于 1 个 table。
这种形式在肯定水平上也能无效防止问题,然而分库分表还会引来查问侧革新的工作量,依然无奈彻底解决问题。然而如果咱们换用专用的时序数据库,就能更好地解决这个问题。
基于 TDengine 建模
TDengine 作为国内 Top 的开源时序数据库,产品定位为「分布式时序数据库」,产品性能专门针对时序数据场景设计和优化,曾经被宽泛使用于金融、车联网、工业互联网等时序数据场景中。曾经落地的「量化投资剖析」场景计划有《TDengine 在同花顺组合治理业务中的优化实际》、《TDengine 在弘源泰平量化投资中的实际》等。
回到下面基于 MySQL 的建模思路,TDengine 的设计外面,也是 1 个证券 1 个 table 的理念,通过超级表(stable)的语法糖,疾速并行查问多个证券的数据;同时针对常见的业务查问场景做了定向的性能优化,从而保障在「海量」数据的状况下,性能仍旧体现坚挺;而且还设置了很多乏味的个性,助力时序解决更加简略。
规范 SQL 语法
TDengine 反对规范 SQL 语法,比老一代的时序数据库,具备更好的上手体验。
动静与静态数据拆散在 TDengine 当中,超级表(stable)构造引入了标签(tag)的概念,这样一来,咱们能够把证券的维度信息放在标签当中,缩小数据存储空间,晋升查问性能。同时,在建模上采纳 1 个证券 1 张表的形式,以此保障高性能读写。
通过超级表语法糖,TDengine 实现了并行查问的能力,大大减少 SQL 的复杂度:
以上便是两种数据库对于上述问题场景的具体解决思路,你感觉如果是你会抉择哪一种呢?能够在评论区进行留言,一起探讨。
总而言之,不论是传统的关系型数据库,还是 NoSQL 数据库,如果咱们没有针对性地去对应时序数据特点,在性能晋升上极为无限,只能依附集群技术,投入更多的计算资源和存储资源来解决,零碎的经营保护老本也会因而急剧回升。如果你也面临着海量时序数据处理难题,无妨能够加一下小 T vx:tdengine1,进入 TDengine 用户交换群,和大家一起来探讨解决门路。