当前位置:首页 > 问答 > 正文

用H2数据库做缓存,人工智能数据处理其实挺方便的,速度也能提升不少

最近在一个项目里,我们尝试用H2数据库来给人工智能的数据处理环节做缓存,发现效果出奇的好,整个过程变得顺手了很多,处理速度也明显快了一大截,这让我觉得,对于很多中小型的人工智能项目或者实验场景来说,H2这种轻量级的数据库,其实是个挺不错却被低估了的缓存选择。

先说说我们当时遇到的情况吧,我们在做一个图像分类模型的训练,需要反复对几十万张图片的特征向量进行读取、组合和变换,这些特征向量是预先用另一个模型提取好的,每条向量都有上千个维度,最开始,我们图省事,直接把这些向量存成了CSV文件和Python的pickle格式,每次启动训练脚本,第一件事就是花上好几分钟甚至更长时间,把这几百兆甚至上G的数据从硬盘读到内存里,这还只是开始,在训练过程中,由于内存有限,有时候无法一次性加载所有数据,需要频繁地读取硬盘上的文件,导致CPU经常闲着等数据,整个训练流程卡顿感很强,效率非常低,这时候,我们就想找个办法,能让数据读取得更快一些。

然后我们就想到了用缓存,一开始也考虑过Redis这类专门的内存缓存数据库,性能确实顶尖,但对我们这个项目来说,引入Redis意味着需要额外搭建和维护一个服务器,增加了一些部署的复杂性,而我们需要的,其实就是一个能快速存取、最好能内嵌在应用里、不需要独立服务进程的解决方案,这时候,H2数据库就进入了视野,根据H2数据库的官方文档介绍,它是一个用Java编写的关系型数据库,最大的特点就是可以嵌入到应用程序中,也可以作为内存数据库使用,也就是说,我们可以创建一个完全在内存里的H2数据库,所有操作都在内存中完成,速度极快,而且当应用程序关闭时,数据库和里面的数据也就随之清空,非常适合做临时性的缓存。

用H2数据库做缓存,人工智能数据处理其实挺方便的,速度也能提升不少

我们就动手试了一下,具体做法是,在训练脚本一开始,启动一个内存模式的H2数据库实例,把原本存储在CSV文件里的那些图片特征向量,批量地、一次性导入到H2数据库的一张表里,这张表的结构很简单,主要就是图片ID和对应的特征向量数据,完成导入后,我们就把原来的CSV文件抛在一边了。

接下来的训练过程,数据读取方式就完全变了,当需要一批数据时,训练程序不再去慢吞吞地读文件,而是向H2数据库发送SQL查询语句,因为整个数据库都运行在内存里,这些查询操作的响应速度非常快,几乎是瞬间就能返回结果,这就好比是把所有需要频繁使用的工具,从远处仓库(硬盘文件)里全都搬到了手边的工作台(内存数据库)上,随用随取,再也不用来回跑腿了,我们发现,尤其是对于那些需要随机访问不同批次数据的训练循环,H2内存数据库带来的速度提升特别明显,CPU等待数据的时间大大减少,GPU的利用率也自然上去了,整个训练周期缩短了不少。

用H2数据库做缓存,人工智能数据处理其实挺方便的,速度也能提升不少

除了速度快,我们还发现H2用起来挺方便的,因为它支持标准的SQL语法,所以我们能用很熟悉的SQL语句来灵活地查询和获取数据,我们可以轻松地实现按特定条件筛选数据、随机抽样一批数据、或者按照某个顺序获取数据,这些操作如果直接操作文件来实现,会写很多繁琐的代码,而用SQL几句话就搞定了,这给我们的数据处理流程带来了很大的灵活性,H2也支持连接磁盘的模式,如果内存不够大,也可以配置成混合模式,部分数据放在内存,部分放在磁盘,提供了更多的可能性。

它也有局限,最主要的就是,因为是内存数据库,所以缓存数据的容量受限于服务器的内存大小,如果我们的特征向量数据量再大一个数量级,比如达到上百GB,可能全部放进内存就不现实了,但在我们当前几十个GB的数据量级下,H2表现得游刃有余,由于是嵌入式数据库,它不适合多应用同时访问的共享缓存场景,但对于我们这种单一的训练进程来说,这根本不是问题。

这次经历让我觉得,对于数据量不是特别庞大的AI数据处理和模型训练任务,如果被硬盘I/O速度拖了后腿,完全可以考虑把H2数据库当作一个轻量级、高性能的缓存工具来用,它搭建简单,使用方便,又能实实在在地提升处理速度,让研究人员和工程师能更专注于算法和模型本身,而不是把时间浪费在等待数据加载上,这可以说是一个投入产出比很高的优化技巧。