如今大模型崛起,当涉及到复杂业务检索时候离不开rag,有很多老铁在研究rag的时候发现都会使用各种向量数据库,和普通数据有什么区别的,其实没区别就是存储,就是对向量专门优化过的存储,实际用mysql也是能实现
mysql存储向量的问题
假设向量是768维度,他是一个数组, 直接存到mysql是没法存的,需要转为字符串,但rag应用是需要做向量的相似度比对,需要在查询的时候还原数组,将输入的向量和每个存储好的文档向量做比对。那问题关键在于数据的读写效率,转成字符串,有多种方法,请看下面案例
public static void main(String[] args) {//构建模拟向量float[] data = new float[768];for (int i = 0; i < data.length; i++) {data[i] = i;}//第一种join splitlong first = System.currentTimeMillis();String join = CollUtil.join(CollUtil.newArrayList(data), ",");String[] split = join.split(",");List<String> newArrayList = CollUtil.newArrayList(split);long second = System.currentTimeMillis();System.out.println("通过join split: " + (second - first));//第二种json序列化String jsonStr = JSONUtil.toJsonStr(data);List<Float> newArrayList2 = JSONUtil.toList(jsonStr, Float.class);long third = System.currentTimeMillis();System.out.println("通过json序列化: " + (third - second));//第三种toString+substringString string = Arrays.toString(data);string = string.substring(1);string = string.substring(0, string.length()-1);String[] split2 = string.split(",");float[] newArrayList3 = new float[split2.length];for (int i = 0; i < split2.length; i++) {newArrayList3[i] = Float.parseFloat(split2[i]);}long four = System.currentTimeMillis();System.out.println("toString+截取: " + (four - third));}
通过join split: 197
通过json序列化: 63
toString+截取: 2
分别使用三种方法评测,假设有1000个文档(向量),使用前面两种方法,检索长则几分钟,对面很明显了,如果采用第三种,那也就是2秒左右。
结论
toString和截取效率是最高的,大家就知道怎么优化了吧
当然如果你大规模还是建议使用文档类数据库或向量数据库