記錄一次優化程序的過程:幾百萬的商品過濾黑名單你會怎麼想?

問題描述:數組

最近遇到一個問題,在程序中,有一個百萬級別的商品集合,須要過濾掉商品黑名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+。程序的過濾時間也縮短至幾秒鐘!

相關文章
相關標籤/搜索