Java 提高矩阵/表聚合和搜索的性能
有一个产品特征矩阵。它有数千行(产品)和数百个功能。它具有二进制值,用于显示产品是否具有此功能。因此,它可能是一个包含40000行和900列的表Java 提高矩阵/表聚合和搜索的性能,java,mysql,algorithm,rdbms,sparse-matrix,Java,Mysql,Algorithm,Rdbms,Sparse Matrix,有一个产品特征矩阵。它有数千行(产品)和数百个功能。它具有二进制值,用于显示产品是否具有此功能。因此,它可能是一个包含40000行和900列的表 产品功能矩阵 pr f1 f2 f3 fn… 01 0 1 1 02 0 0 0310110 041010 ..... 首先,我必须找到具有一组给定特性Q的产品,例如Q=(f1=1,f5=1,f27=1)。简单的说,找到蓝色的车,掀背式的,三门的 结果1 给定Q=(f1=1,f5=1,f27=1) 相关产品:03、04、08。。。 第二,也是最
产品功能矩阵
pr f1 f2 f3 fn…
01 0 1 1
02 0 0
0310110
041010
.....
首先,我必须找到具有一组给定特性Q的产品,例如Q=(f1=1,f5=1,f27=1)。简单的说,找到蓝色的车,掀背式的,三门的
结果1
给定Q=(f1=1,f5=1,f27=1)
相关产品:03、04、08。。。
第二,也是最重要的,我必须找出有多少产品有一组特性Q,也有一个特性f_I(其中I-1..n)。换句话说,我们选择满足Q的行,并计算每列中有多少个1(进行总和聚合)。例如,有多少辆蓝色轿车、掀背车、三门车也有:柴油机、汽油机、氙气灯
结果2
给定Q=(f1=1,f5=1,f27=1)
总和f2=943
总和f3=543
总和f4=7
总和f6=432
....
当然,使用RDBMS解决这个任务是可能的,但它并不是那么有效——在一般情况下,它需要在每个列中进行完整扫描以查找产品和聚合。至少我不知道如何为这个任务构建有效的b树索引。Oracle位图索引可能会有所帮助,但我不能使用Oracle
目前,我们正在使用MySQL来完成这项任务,但效果不佳。实际上,我们使用整数表示(我们将特征分组并将整数存储在列中,而不是布尔值)来减少列的数量
可以将此矩阵视为稀疏二进制矩阵。把它完全存储在内存中并不是什么大问题。我想知道是否可以应用一些算法来处理稀疏矩阵、向量空间(SVD、矩阵向量乘法等等)。但它可能有助于找到满足向量Q的乘积,而不是聚合。问题更多地在于聚合的时间,而不是空间
也许,可以将矩阵存储为一个多链接列表,这将有助于查找产品并对每个列进行聚合
最后,问题是如何对待这项任务。查找具有给定功能的产品,然后计算具有附加功能的产品(按每列聚合)的最有效算法是什么。如果我了解您当前的解决方案,您有一个表,其中每个产品有一行,每个功能有一列。这是一种解决问题的低效方法 三张桌子怎么样 “产品”(产品编号、产品名称)索引产品编号(产品清单) “特征”(特征参考,描述)索引特征参考(可能特征的列表) 及 “productfeatures”(product_ref,feature_ref)索引product_ref,feature_ref和feature_ref,product_ref(每行代表一个产品的特征) 然后可以在表之间执行联接
从产品t1中选择*加入产品功能t2加入产品功能t3,其中t1.product\u ref=t2.product\u ref和t1.product\u ref=t3.product\u ref和t2.feature\u ref=45和t3.feature\u ref=67等请看一看我刚才做的这个示例,它遵循Jayde正确概述的内容,但更详细地说,相对于运行时间为0.02秒的1.25亿海报类别(汽车功能),最坏的情况是40K++*900列=3600万行,也就是说,这是一个婴儿
您可以按列排列数据。i、 e.为列中列出具有该特性的车辆/行设置一个位集 这允许您利用位集提供的快速和/或操作 使用这些功能,您应该能够实现少于2微秒的搜索和每个功能的计数 对于40000*900数据集,打印以下内容
average search time 1396 ns.
average count time 1234 ns.
这应该比使用RDBMS数据库快几个数量级。即使是一百万行,每行也不到50微秒
public static void main(String... args) throws IOException {
final int rows = 40 * 1000;
final int cols = 900;
List<BitSet> features = new ArrayList<BitSet>();
features.add(new BitSet(rows));
features.add(new BitSet(rows));
for (int i = 2; i < cols; i++) {
final BitSet bs = new BitSet(rows);
for (int j = 0; j < rows; j++)
bs.set(j, j % i == 0);
features.add(bs);
}
// perform the search
int[] factors = new int[]{2, 5, 7};
BitSet matches = new BitSet();
long runs = 1000*1000;
{
long start = System.nanoTime();
for (int i = 0; i < runs; i++) {
// perform lookup.
lookup(matches, features, factors);
}
long avgTime = (System.nanoTime() - start) / runs;
System.out.println("average search time " + avgTime + " ns.");
}
{
long start = System.nanoTime();
int count9 = 0;
BitSet col9matched = new BitSet(cols);
for (int i = 0; i < runs; i++) {
final int index = 9;
final BitSet feature = features.get(index);
count9 = countMatches(col9matched, matches, feature);
}
long avgTime = (System.nanoTime() - start) / runs;
System.out.println("average count time " + avgTime + " ns.");
}
}
private static int countMatches(BitSet scratch, BitSet matches, BitSet feature) {
// recycle.
scratch.clear();
scratch.or(matches);
scratch.and(feature);
return scratch.cardinality();
}
private static void lookup(BitSet matches, List<BitSet> data, int[] factors) {
matches.clear();
matches.or(data.get(factors[0]));
for (int i = 1, factorsLength = factors.length; i < factorsLength; i++) {
matches.and(data.get(factors[i]));
}
}
publicstaticvoidmain(String…args)抛出IOException{
最终整数行=40*1000;
最终整数cols=900;
列表功能=新建ArrayList();
添加(新的位集(行));
添加(新的位集(行));
for(int i=2;ipublic static void main(String... args) throws IOException {
final int rows = 40 * 1000;
final int cols = 900;
List<BitSet> features = new ArrayList<BitSet>();
features.add(new BitSet(rows));
features.add(new BitSet(rows));
for (int i = 2; i < cols; i++) {
final BitSet bs = new BitSet(rows);
for (int j = 0; j < rows; j++)
bs.set(j, j % i == 0);
features.add(bs);
}
// perform the search
int[] factors = new int[]{2, 5, 7};
BitSet matches = new BitSet();
long runs = 1000*1000;
{
long start = System.nanoTime();
for (int i = 0; i < runs; i++) {
// perform lookup.
lookup(matches, features, factors);
}
long avgTime = (System.nanoTime() - start) / runs;
System.out.println("average search time " + avgTime + " ns.");
}
{
long start = System.nanoTime();
int count9 = 0;
BitSet col9matched = new BitSet(cols);
for (int i = 0; i < runs; i++) {
final int index = 9;
final BitSet feature = features.get(index);
count9 = countMatches(col9matched, matches, feature);
}
long avgTime = (System.nanoTime() - start) / runs;
System.out.println("average count time " + avgTime + " ns.");
}
}
private static int countMatches(BitSet scratch, BitSet matches, BitSet feature) {
// recycle.
scratch.clear();
scratch.or(matches);
scratch.and(feature);
return scratch.cardinality();
}
private static void lookup(BitSet matches, List<BitSet> data, int[] factors) {
matches.clear();
matches.or(data.get(factors[0]));
for (int i = 1, factorsLength = factors.length; i < factorsLength; i++) {
matches.and(data.get(factors[i]));
}
}