记录一次优化程序的过程:几百万的商品过滤黑名单你会怎么想?

问题描述:数组

最近遇到一个问题,在程序中,有一个百万级别的商品集合,须要过滤掉商品黑名ide


单,这个黑名单由运营同窗手工配置,从原来的几个到几百个,再到上千个,致使现spa


在程序在过滤这块耗时太长。如何使得程序的过滤运行时间缩短呢?日志


分析:orm


好比,咱们的商品集合是Map<ID,Product> skuMap,ID为商品的ID,Product是商品类型对象


对象,大小是100W+,商品黑名单列表是每隔10MIN去读取一次造成long[] skus,数组的排序


元素放置的就是商品ID,数组大小是几千级别。get



过滤方案:it


方案一:
io


伪码:


for(Product p : skuMap){


  for(Long id : skus){


    if(p.getId() == id){

      //此商品被过滤掉

      p.setFlag(false);

     }

   }

}


这种方案,是最初的写法,想法比较简单,就是2层FOR循环。


可是,随着配置的黑名单愈来愈多,从最初的几个到几百个,最后到几千个级别,致使


这段代码运行时间发生波动,而且愈来愈长!



方案二:


如何缩短期呢?


对于方案一,而言,100W+的商品中的每个商品都必须对skus进行所有遍历才能完成过


滤逻辑,致使循环次数是 100W+ * 1000+ 级别,也就是10亿+的级别,循环的次数实在


是太多了!要缩短循环次数,才能缩短期!


伪码:


Arrays.sort(skus);


for(Product p : skuMap){


   int result = Arrays.binarySearch(skus,id);


   if(result < 0){

      p.setFlag(false);

   }

}


若是咱们在拿到skus后,对skus内部的ID进行一次排序,而后每一个商品对skus进行二分


查找。要知道1000+的黑名单,对于二分查找而言,最多查找11次就能够找到!也就是在


最坏的状况下,咱们须要循环的次数变成了100W+ * 11,即1000W+的循环次数!


这样方案二,一会儿将10亿+的循环次数缩短至1000W+。


虽然如此,可是程序的过滤时间,日志打印,居然是300S+,这也没法接受!



方案三:


咱们为何要拿skuMap取遍历skus,为何不用黑名单去过滤商品集合呢?


伪码:


for(long sku : skus){


  if(skuMap.containsKey(sku)){

     skuMap.get(sku).setFlag(false);

  }


}


外层循环,变成了黑名单,在内部要知道咱们用的是HASHMAP查找,实际上,一会儿,循环次数变成了1000+。程序的过滤时间也缩短至几秒钟!

相关文章
相关标签/搜索