mysql旧版本存储嵌入模型的向量数据
mysql 9.0开始支持向量(VECTOR)数据类型,社区褒贬不一,虽然它的功能还比较简陋,不过对于保存嵌入模型向量化的数据,还是非常有帮助的,而在mysql以前的版本中,我们的方案主要还是使用blob数据类型的字段来保存向量数据的内存数据。其实现在很多单位还在使用mysql的旧版本,并没有都跟新上mysql 9。以下主要介绍下mysql使用blob字段存储向量数据后续可能会遇到的小坑。
我有一个nodejs开发的程序,对一些新闻标题使用嵌入模型进行处理后将向量数据保存在mysql中,后续会取出跟其他的标题向量进行语义匹配,就这个简单的写入和读出就遇到问题了。
我使用的是一个4096维的嵌入模型,会将每一个新闻标题转换成一个包含4096个浮点数的数组,
let float32Array = new Float32Array(titlevector);
let buffer=Buffer.from(float32Array.buffer);
将buffer作为字段值通过insert语句插入表格即可,没有什么毛病。
读取的话,执行SQL查询,得到返回的结果集dbchklist
dbchklist.forEach(item => {const blob = item.tvb;item.tv= new Float32Array(blob.buffer, blob.byteOffset, 4096);});
好像没有毛病,但是执行时报错了
RangeError: start offset of Float32Array should be a multiple of 4at new Float32Array (<anonymous>)
Float32Array要求缓存得从4的倍数的地址开始!而在 Node.js 中使用 mysql2 库时,无法直接确保返回的 blob 对象内存对齐,这是由底层实现决定的。对于没有对齐的,可以创建新的对齐内存,使用高效 Uint8Array.set() 复制数据。
dbchklist.forEach(item => {const blob = item.tvb;if (blob.byteOffset % 4 === 0) {item.tv= new Float32Array(blob.buffer, blob.byteOffset, 4096);}else {const arrayBuffer = new ArrayBuffer(16384);const sourceView = new Uint8Array(blob.buffer, blob.byteOffset, 16384);new Uint8Array(arrayBuffer).set(sourceView);item.tv=new Float32Array(arrayBuffer);}});
这样就可以正常把blob保存的向量数据正常读出了。