如何優(yōu)化大數(shù)據(jù)量的方法

隨著項(xiàng)目上線功氨,業(yè)務(wù)數(shù)據(jù)會(huì)越來越多。這個(gè)時(shí)候手幢,很多開發(fā)時(shí)適用的方法捷凄、任務(wù),在龐大數(shù)據(jù)量面前就會(huì)變得很不堪围来,經(jīng)常會(huì)出現(xiàn)超時(shí)跺涤,慢查詢,異常等等問題监透。

所以没酣,一般在開發(fā)階段勋眯,我們?cè)趺茨鼙苊膺@些問題呢?一切皆有套路。

一般處理套路:
SQL優(yōu)化缤言,數(shù)據(jù)庫(kù)加索引罗心,多線程,并行計(jì)算,異步處理超营,大事務(wù)拆小事務(wù),緩存阅虫,數(shù)據(jù)異構(gòu)等等演闭。

今天分享一個(gè)通過時(shí)間維度優(yōu)化SQL的方法。說白了颓帝,就是如何將時(shí)間拆小米碰。

還是直接貼代碼:

開始版本,按天拆分時(shí)間:

/**
     * 按給定的天數(shù)切割時(shí)間段
     * @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();//開始時(shí)間
        Calendar canlandar2 = Calendar.getInstance();//結(jié)束時(shí)間
        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);//每次循環(huán)增加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;
    }

發(fā)現(xiàn)某些天數(shù)據(jù)量大跑不動(dòng)了购城,然后繼續(xù)拆分成小時(shí):

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();//開始時(shí)間
        Calendar canlandar2 = Calendar.getInstance();//結(jié)束時(shí)間
        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);//每次循環(huán)增加一天
            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;
    }

最后發(fā)現(xiàn)光棍節(jié)的這天吕座,小時(shí)也跑不動(dòng)了,還要繼續(xù)拆分鐘瘪板?改成自己拆吧吴趴。

/**
 * @Auther: majx2
 * @Date: 2018-11-14 11:24
 * @Description:
 */
public class JobTimeoutHelper {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
// 時(shí)間區(qū)間拆分?jǐn)?shù)量    
private int intervalCount = 3;
// 拆分最大層級(jí)
    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("{}超時(shí),拆分已到上限侮攀,無(wú)法繼續(xù)拆分:時(shí)間:{}",jobName,MessageFormat.format("開始時(shí)間:{0}锣枝,結(jié)束時(shí)間:{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("{}處理開始,層級(jí):{}兰英,時(shí)間:{}", jobName,level,MessageFormat.format("開始時(shí)間:{0}撇叁,結(jié)束時(shí)間:{1}",df.format(start),df.format(end)));
                    handler.deal(start,end);
                    logger.info("{}處理結(jié)束,層級(jí):{}畦贸,時(shí)間:{}", jobName,level,MessageFormat.format("開始時(shí)間:{0}陨闹,結(jié)束時(shí)間:{1}",df.format(start),df.format(end)));
                }catch (MySQLNonTransientConnectionException ex){
                    logger.info("{}超時(shí),進(jìn)行拆分處理薄坏,層級(jí):{}",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();
            }
        });
    }
}

這是一個(gè)任務(wù)超時(shí)幫助類趋厉,原來是通過遞歸的方式,不斷將時(shí)間拆小胶坠,這樣在龐大的數(shù)據(jù)面前也可以淡定的run起來君账。只需要多花點(diǎn)時(shí)間而已。同時(shí)涵但,也可以配合多線程處理,讓程序加速奔跑起來帖蔓。

溫馨提示:要根據(jù)實(shí)際需求矮瘟,記得要設(shè)置多少等份,和最大層級(jí)哦塑娇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末澈侠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子埋酬,更是在濱河造成了極大的恐慌哨啃,老刑警劉巖烧栋,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拳球,居然都是意外死亡审姓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門祝峻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魔吐,“玉大人,你說我怎么就攤上這事莱找〕昴罚” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵奥溺,是天一觀的道長(zhǎng)辞色。 經(jīng)常有香客問我,道長(zhǎng)浮定,這世上最難降的妖魔是什么相满? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮壶唤,結(jié)果婚禮上雳灵,老公的妹妹穿的比我還像新娘。我一直安慰自己闸盔,他們只是感情好悯辙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著迎吵,像睡著了一般躲撰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上击费,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天拢蛋,我揣著相機(jī)與錄音,去河邊找鬼蔫巩。 笑死谆棱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的圆仔。 我是一名探鬼主播垃瞧,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼坪郭!你這毒婦竟也來了个从?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嗦锐,沒想到半個(gè)月后嫌松,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奕污,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年萎羔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片菊值。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡外驱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腻窒,到底是詐尸還是另有隱情昵宇,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布儿子,位于F島的核電站瓦哎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏柔逼。R本人自食惡果不足惜蒋譬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望愉适。 院中可真熱鬧犯助,春花似錦、人聲如沸维咸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)癌蓖。三九已至瞬哼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間租副,已是汗流浹背坐慰。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留用僧,地道東北人结胀。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像责循,于是被迫代替她去往敵國(guó)和親糟港。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,930評(píng)論 2 89
  • 本文是我自己在秋招復(fù)習(xí)時(shí)的讀書筆記沼死,整理的知識(shí)點(diǎn)着逐,也是為了防止忘記崔赌,尊重勞動(dòng)成果意蛀,轉(zhuǎn)載注明出處哦耸别!如果你也喜歡,那...
    波波波先森閱讀 11,258評(píng)論 4 56
  • Java繼承關(guān)系初始化順序 父類的靜態(tài)變量-->父類的靜態(tài)代碼塊-->子類的靜態(tài)變量-->子類的靜態(tài)代碼快-->父...
    第六象限閱讀 2,154評(píng)論 0 9
  • 當(dāng)我年輕時(shí)县钥,時(shí)間總是過得特別快秀姐。 當(dāng)我年輕時(shí),有些事有些人總是無(wú)法介懷和放手若贮。 當(dāng)我年輕時(shí)省有,每天清晨起來總覺得要傾...
    生活故事錄閱讀 315評(píng)論 0 1
  • 隱居在郊野,夏日有余閑谴麦。 朝觀紅蓮開蠢沿,夜枕蛙聲眠。 柴門聞犬吠匾效,隔窗鳥飛還舷蟀。 平生許多事,都作浮云散面哼。
    云無(wú)心隨緣閱讀 332評(píng)論 1 1