美文网首页
如何优化大数据量的方法

如何优化大数据量的方法

作者: DreamsonMa | 来源:发表于2018-11-14 21:53 被阅读0次

    随着项目上线,业务数据会越来越多。这个时候,很多开发时适用的方法、任务,在庞大数据量面前就会变得很不堪,经常会出现超时,慢查询,异常等等问题。

    所以,一般在开发阶段,我们怎么能避免这些问题呢?一切皆有套路。

    一般处理套路:
    SQL优化,数据库加索引,多线程,并行计算,异步处理,大事务拆小事务,缓存,数据异构等等。

    今天分享一个通过时间维度优化SQL的方法。说白了,就是如何将时间拆小。

    还是直接贴代码:

    开始版本,按天拆分时间:

    /**
         * 按给定的天数切割时间段
         * @param startDate
         * @param endDate
         * @param amount 按多少天切割
         * @return
         * @throws ParseException
         */
        public static List<TimeSlot> splitTimeSlot(Date startDate, Date endDate, Integer amount) throws ParseException {
            Calendar canlandar1 = Calendar.getInstance();//开始时间
            Calendar canlandar2 = Calendar.getInstance();//结束时间
            canlandar1.setTime(com.midea.ec.fc.impl.utils.DateUtils.getDateStartTime(startDate));
            canlandar2.setTime(com.midea.ec.fc.impl.utils.DateUtils.getDateStartTime(endDate));
            List<TimeSlot> returnList = new ArrayList<TimeSlot>();
            while(canlandar1.compareTo(canlandar2) < 1){
                TimeSlot timeSlot = new TimeSlot();
                Date start = canlandar1.getTime();
                canlandar1.add(Calendar.DATE, amount);//每次循环增加amount天
                Date end = canlandar1.getTime();
                timeSlot.setStartDate(DateTool.getDateTime(start));
                timeSlot.setEndDate(DateTool.getDateTime(end.before(canlandar2.getTime()) ? end : canlandar2.getTime()));
                returnList.add(timeSlot);
                timeSlot.setStartDateTime(start);
                timeSlot.setEndDateTime(end.before(canlandar2.getTime()) ? end : canlandar2.getTime());
            }
            return returnList;
        }
    

    发现某些天数据量大跑不动了,然后继续拆分成小时:

    public static List<TimeSlot> splitTimeSlotByHour(String startDate, String endDate) throws ParseException {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Date date1 = format.parse(startDate);
            Date date2 = format.parse(endDate);
    
            Calendar canlandar1 = Calendar.getInstance();//开始时间
            Calendar canlandar2 = Calendar.getInstance();//结束时间
            canlandar1.setTime(date1);//2016-11-01
            canlandar2.setTime(date2);//2016-11-11
            List<TimeSlot> returnList = new ArrayList<TimeSlot>();
            while(canlandar1.compareTo(canlandar2) < 1){
                TimeSlot timeSlot = new TimeSlot();
                Date start = canlandar1.getTime();
                canlandar1.add(Calendar.HOUR, 1);//每次循环增加一天
                Date end = canlandar1.getTime();
                timeSlot.setStartDate(DateTool.getDateTime(start));
                timeSlot.setEndDate(DateTool.getDateTime(end));
                returnList.add(timeSlot);
                timeSlot.setStartDateTime(start);
                timeSlot.setEndDateTime(end);
            }
            if(CollectionUtils.isNotEmpty(returnList)) returnList.remove(returnList.size()-1);
            return returnList;
        }
    

    最后发现光棍节的这天,小时也跑不动了,还要继续拆分钟?改成自己拆吧。

    /**
     * @Auther: majx2
     * @Date: 2018-11-14 11:24
     * @Description:
     */
    public class JobTimeoutHelper {
    
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    // 时间区间拆分数量    
    private int intervalCount = 3;
    // 拆分最大层级
        private int maxCount = 3;
    
        private JobTimeoutHelper(){}
        public static JobTimeoutHelper create(){
            return new JobTimeoutHelper();
        }
    
        public void splitTime(Date startDate,Date endDate,String jobName,TimeSplitHandler handler){
            splitTime(startDate,endDate,0,jobName,handler);
        }
    
        public void splitTime(Date startDate,Date endDate,int level,String jobName,TimeSplitHandler handler){
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if(level>=maxCount){
                logger.info("{}超时,拆分已到上限,无法继续拆分:时间:{}",jobName,MessageFormat.format("开始时间:{0},结束时间:{1}",df.format(startDate),df.format(endDate)));
                return;
            }
            level++;
            if(startDate.compareTo(endDate) < 1) {
                long offset = startDate.getTime();
                long diff = endDate.getTime() - offset;
                long interval = diff/intervalCount;
                for (int i = 0 ; i <intervalCount;i++){
                    Date start = new Date(offset);
                    Date end ;
                    if(i == (intervalCount-1)){
                        end = endDate;
                    }else{
                        offset += interval;
                        end =  new Date(offset);
                    }
                    try{
                        logger.info("{}处理开始,层级:{},时间:{}", jobName,level,MessageFormat.format("开始时间:{0},结束时间:{1}",df.format(start),df.format(end)));
                        handler.deal(start,end);
                        logger.info("{}处理结束,层级:{},时间:{}", jobName,level,MessageFormat.format("开始时间:{0},结束时间:{1}",df.format(start),df.format(end)));
                    }catch (MySQLNonTransientConnectionException ex){
                        logger.info("{}超时,进行拆分处理,层级:{}",jobName,level);
                        splitTime(start,end,level,jobName,handler);
                    } catch (Exception e) {
                        logger.error("{}异常啦:{}",jobName, ExceptionUtils.getFullStackTrace(e));
                    }
                }
            }
        }
    
        public interface TimeSplitHandler{
            void deal(Date start,Date end) throws Exception;
        }
    
        public JobTimeoutHelper setIntervalCount(int intervalCount) {
            this.intervalCount = intervalCount;
            return this;
        }
    
        public JobTimeoutHelper setMaxCount(int maxCount){
            this.maxCount = maxCount;
            return this;
        }
    
    
        public static void main(String[] args) {
            final Date today = new Date();
            final Date tomorrow = DateUtils.addDays(today, +1);
            final Date yestoday = DateUtils.addDays(today, -1);
            JobTimeoutHelper.create().setIntervalCount(2).setMaxCount(3)
                    .splitTime(yestoday, tomorrow,"JobTimeoutHelper", new TimeSplitHandler() {
                @Override
                public void deal(Date start, Date end) throws Exception {
                    throw new MySQLNonTransientConnectionException();
                }
            });
        }
    }
    

    这是一个任务超时帮助类,原来是通过递归的方式,不断将时间拆小,这样在庞大的数据面前也可以淡定的run起来。只需要多花点时间而已。同时,也可以配合多线程处理,让程序加速奔跑起来。

    温馨提示:要根据实际需求,记得要设置多少等份,和最大层级哦。

    相关文章

      网友评论

          本文标题:如何优化大数据量的方法

          本文链接:https://www.haomeiwen.com/subject/fqusfqtx.html