B2B2B2C 電商系統(tǒng)首頁(yè)導(dǎo)航優(yōu)化

image.png

定位問(wèn)題

  1. 日志里出現(xiàn)了幾千次這樣的sql
mapper.BrandMapper.findByClassId - ========>  Preparing: select brand_id, brand_name, brand_class, brand_pic, brand_sort, brand_recommend, store_id,brand_apply, class_id,is_del,create_time,update_time from shop_brand where class_id = ? and is_del = 0 and brand_apply = 1 order by brand_sort desc 

GoodsClassCustomMapper.findChild - ========>  Preparing: SELECT gc_id,gc_parent_id,gc_rel_gcid,gc_name,gc_pic,gc_sort,gc_show,gc_title,gc_keywords, gc_description,gc_idpath,gc_url,gc_adduser,gc_upuser,gc_advid,create_time, update_time , (select count(*) from shop_goods_class_custom s1 where s1.gc_parent_id=s.gc_id ) has_child FROM shop_goods_class_custom s where gc_parent_id = ? and gc_show=1 order by gc_sort DESC 

這肯定是循環(huán)執(zhí)行了sql了。所以,需要找循環(huán)執(zhí)行的地方齿椅。

  1. 通過(guò)全局搜索 findByClassIdfindChild 兩個(gè)函數(shù)启泣,且是循環(huán)執(zhí)行的地方涣脚,發(fā)現(xiàn)可能是 Mapper 里出的問(wèn)題:
    <resultMap id="BaseResultMap" type="com.leimingtech.core.entity.GoodsClass">
        <id column="gc_id" property="gcId" jdbcType="VARCHAR"/>
        <result column="gc_name" property="gcName" jdbcType="VARCHAR"/>
        <result column="gc_pic" property="gcpic" jdbcType="VARCHAR"/>
        <result column="type_id" property="typeId" jdbcType="VARCHAR"/>
        <result column="type_name" property="typename" jdbcType="VARCHAR"/>
        <result column="gc_parent_id" property="gcParentId" jdbcType="VARCHAR"/>
        <result column="gc_sort" property="gcSort" jdbcType="INTEGER"/>
        <result column="gc_show" property="gcshow" jdbcType="INTEGER"/>
        <result column="gc_title" property="gcTitle" jdbcType="VARCHAR"/>
        <result column="gc_keywords" property="gcKeywords" jdbcType="VARCHAR"/>
        <result column="gc_description" property="gcDescription" jdbcType="VARCHAR"/>
        <result column="gc_idpath" property="gcIdpath" jdbcType="VARCHAR"/>
        <result column="has_child" property="hasChild" jdbcType="INTEGER"/>
        <result column="expen_scale" property="expenScale" jdbcType="FLOAT"/>
        <result column="is_relate" property="isRelate" jdbcType="INTEGER"/>
        <result column="virtual_goods" property="virtualGoods" jdbcType="INTEGER"/>
        <result column="relation" property="relation" jdbcType="INTEGER"/>
        <collection property="classList" ofType="com.leimingtech.core.entity.GoodsClass"
                    column="gc_id" javaType="arraylist"
                    select="com.leimingtech.service.module.goods.dao.mapper.GoodsClassMapper.findChild">
        </collection>
        <collection property="brandList" ofType="com.leimingtech.core.entity.base.Brand" column="gc_id"
                    javaType="arrayList"
                    select="com.leimingtech.service.module.goods.dao.mapper.BrandMapper.findByClassId">
        </collection>
    </resultMap>

這個(gè)文件里,這兩個(gè)sql是同時(shí)出現(xiàn)的寥茫,正好和日志里出現(xiàn)的模式一樣遣蚀。這樣的文件有兩個(gè)

C:\opt\zzwelfare\welfare-service\src\main\resources\com\leimingtech\service\module\goods\dao\mapper\GoodsClassCustomMapper.xml
C:\opt\zzwelfare\welfare-service\src\main\resources\com\leimingtech\service\module\goods\dao\mapper\GoodsClassMapper.xml
  1. GoodsClassCustomMapper使用了 BaseResultMap 的地方有:
     <!--遞歸查詢所有分類-->
    <select id="findAllbyisshow" resultMap="BaseResultMap" parameterType="com.leimingtech.core.entity.GoodsClassCustom">
        SELECT
        <include refid="Base_Column_List" />,
        (select count(*) from shop_goods_class_custom s1 where s1.gc_parent_id=s.gc_id and s1.gc_show=#{gcshow}) has_child
        FROM shop_goods_class_custom s where gc_parent_id ='0'
        <if test="gcshow != null and gcshow != ''">
            and gc_show=#{gcshow}
        </if>
        order by gc_sort DESC
    </select>

注釋里居然還寫了遞歸查詢所有分類

優(yōu)化目標(biāo):去掉 mapper 里的循環(huán)查詢

使用了 findAllbyisshow 的地方有:

welfare-api/src/main/java/com/leimingtech/extend/module/api/GoodsApi.java
welfare-front/src/main/java/com/leimingtech/front/module/tag/EgoodsClassCustomProductTag.java
welfare-front/src/main/java/com/leimingtech/front/module/tag/EgoodsClassProductTag.java
welfare-front/src/main/java/com/leimingtech/front/module/tag/GoodsClassCustomTag.java
welfare-front/src/main/java/com/leimingtech/front/module/tag/GoodsClassTag.java
welfare-h5/src/main/java/com/leimingtech/extend/module/h5/category/CategoryHtml5Action.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/dao/GoodsClassCustomDao.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/dao/GoodsClassDao.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/dao/impl/GoodsClassCustomDaoImpl.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/dao/impl/GoodsClassDaoImpl.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/dao/mapper/GoodsClassCustomMapper.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/dao/mapper/GoodsClassMapper.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/service/GoodsClassCustomService.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/service/GoodsClassService.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/service/impl/GoodsClassCustomServiceImpl.java
welfare-service/src/main/java/com/leimingtech/service/module/goods/service/impl/GoodsClassServiceImpl.java

總共這16個(gè)地方。首頁(yè)纱耻,或者類似首頁(yè)用的有:

  1. welfare-service/src/main/java/com/leimingtech/service/module/goods/service/GoodsClassCustomService.java
    /**
     * 查詢所有的分類
     * @return
     */
    @Override
    public List<GoodsClassCustom> findAllbyisshow(GoodsClassCustom goodsClassCustom) {
        List<GoodsClassCustom> gclzs = null;
        if(JedisConfig.JEDIS_STATUS){
            ////需要安裝redis
            Object obj = JedisUtils.getObject(JedisConfig.GCLZ_PREFIX + "goodsClassCustom");
            if(obj == null){
                gclzs = goodsClassCustomDao.findAllbyisshow(goodsClassCustom);
                //10分鐘
                JedisUtils.setObject(JedisConfig.GCLZ_PREFIX + "goodsClassCustom", gclzs, JedisConfig.JEDIS_EXPIRE);
                log.debug(JedisConfig.GCLZ_PREFIX + "存入redis");
            }else{
                gclzs = (List<GoodsClassCustom>)obj;
                log.debug(JedisConfig.GCLZ_PREFIX + "轉(zhuǎn)化成功");
            }
        }else{
            gclzs = goodsClassCustomDao.findAllbyisshow(goodsClassCustom);
        }
        return gclzs;
    }

調(diào)用了這個(gè)方法的地方有:

C:\opt\zzwelfare\welfare-front\src\main\java\com\leimingtech\front\module\tag\GoodsClassCustomTag.java
C:\opt\zzwelfare\welfare-front\src\main\java\com\leimingtech\front\module\tag\EgoodsClassCustomProductTag.java
C:\opt\zzwelfare\welfare-h5\src\main\java\com\leimingtech\extend\module\h5\category\CategoryHtml5Action.java

使用了 GoodsClassCustomTag 的地方有:

C:\opt\zzwelfare\welfare-front\src\main\webapp\WEB-INF\views_v4.0\commons\header.ftl
C:\opt\zzwelfare\welfare-front\src\main\webapp\WEB-INF\views_v4.0\search\goods-search.ftl
C:\opt\zzwelfare\welfare-front\src\main\webapp\WEB-INF\views_v4.0\category\all_class.ftl

header.ftl 中使用 GoodsClassCustomTag 的地方

        <#--<#assign goodsClassTag = newTag("goodsClassTag") />-->
        <#assign goodsClassTag = newTag("goodsClassCustomTag") />
        <#assign goodsList = goodsClassTag("") />
        <#if goodsList?exists && goodsList?size gt 0>
            <#list goodsList as class>
            <li class="classes masonry-brick">
                <div class="title">
                    <#if class.gcUrl ??&& class.gcUrl!=null>
                        <a href="${class.gcUrl}">${class.gcName}</a>
                    <#else>
                        <i></i> <a href="${base}/search/goodsSearch?searchType=gcIdSearch&keyword=${class.gcId}" title="${class.gcName}">${class.gcName}</a>
                    </#if>

                </div>
                <#if class.hasChild gt 0>
                <#assign firstchild = class.classCustomList>
                <#list firstchild as firstclass>
                    <dl>
                        <dt>
                            <#if firstclass.gcUrl ??&& firstclass.gcUrl!=null>
                                <a href="${firstclass.gcUrl}">${firstclass.gcName}</a>
                            <#else>
                                <a href="${base}/search/goodsSearch?searchType=gcIdSearch&keyword=${firstclass.gcRelId}" title="${firstclass.gcName}">${firstclass.gcName}</a>
                            </#if>
                        </dt>
                        <dd>
                            <#if firstclass.hasChild gt 0>
                            <#assign secondchild = firstclass.classCustomList>
                            <#list secondchild as secondclass>
                                <#if secondclass.gcUrl ??&& secondclass.gcUrl!=null>
                                    <a href="${secondclass.gcUrl}">${secondclass.gcName}</a>
                                <#else>
                                    <a href="${base}/search/goodsSearch?searchType=gcIdSearch&keyword=${secondclass.gcRelId}" title="${secondclass.gcName}">${secondclass.gcName}</a>
                                </#if>
                            </#list>
                            </#if>
                        </dd>
                    </dl>
                </#list>
                </#if>
            </li>
            </#list>
        </#if>

這段代碼芭梯,分別使用了結(jié)果集的 classCustomList、但是并沒有用到brandList弄喘。假如僅僅只去掉 brandList 的嵌套玖喘,會(huì)加快一倍的加載時(shí)間。

同時(shí)注意蘑志,classCustomList是嵌套兩層用的累奈。也就是說(shuō),如果不嵌套執(zhí)行sql的話急但,而是使用Java來(lái)處理結(jié)果集澎媒,也只嵌套兩層就可以了。

為了不影響其他使用 findAllbyisshow 的地方羊始,新建一個(gè)方法: findAllbyisshowWithoutRecursion 處理查詢結(jié)果集

C:\opt\zzwelfare\welfare-service\src\main\resources\com\leimingtech\service\module\goods\dao\mapper\GoodsClassCustomMapper.xml

    <!--非遞歸查詢所有分類-->
    <select id="findAllbyisshowWithoutRecursion" resultMap="BaseResultMap8" parameterType="com.leimingtech.core.entity.GoodsClassCustom">
        SELECT
        s.gc_id,s.gc_parent_id,s.gc_rel_gcid,s.gc_name,s.gc_pic,s.gc_sort,s.gc_show,s.gc_title,s.gc_keywords,
        s.gc_description,s.gc_idpath,s.gc_url,s.gc_adduser,s.gc_upuser,s.gc_advid,s.create_time,s.update_time
        FROM shop_goods_class_custom s
        where
        <if test="gcshow != null and gcshow != ''">
             s.gc_show=#{gcshow}
        </if>
        order by s.gc_sort DESC
    </select>

注意這里去掉了 gc_parent_id ='0' 這個(gè)條件

用Java處理返回結(jié)果集:

C:\opt\zzwelfare\welfare-service\src\main\java\com\leimingtech\service\module\goods\service\impl\GoodsClassCustomServiceImpl.java

    /**
     * 查詢所有的分類
     * @return
     */
    @Override
    public List<GoodsClassCustom> findAllbyisshowWithoutRecursion(GoodsClassCustom goodsClassCustom) {
        List<GoodsClassCustom> gclzs = new ArrayList<>();
        List<GoodsClassCustom> allCategoryList = null;
        if(JedisConfig.JEDIS_STATUS){
            ////需要安裝redis
            Object obj = JedisUtils.getObject(JedisConfig.GCLZ_PREFIX + "goodsClassCustom");
            if(obj == null){
                allCategoryList = goodsClassCustomDao.findAllbyisshowWithoutRecursion(goodsClassCustom);
                //10分鐘
                JedisUtils.setObject(JedisConfig.GCLZ_PREFIX + "goodsClassCustom", allCategoryList, JedisConfig.JEDIS_EXPIRE);
                log.debug(JedisConfig.GCLZ_PREFIX + "存入redis");
            }else{
                allCategoryList = (List<GoodsClassCustom>)obj;
                log.debug(JedisConfig.GCLZ_PREFIX + "轉(zhuǎn)化成功");
            }
        }else{
            allCategoryList = goodsClassCustomDao.findAllbyisshowWithoutRecursion(goodsClassCustom);
        }
        if(null != allCategoryList && allCategoryList.size() > 0) {
            for(GoodsClassCustom children: allCategoryList) {

                // 頂層:ParentId == 0
                if(children.getGcParentId().equals("0")) {
                    GoodsClassCustom custom = new GoodsClassCustom();
                    custom.setGcId(children.getGcId());
                    custom.setGcParentId(children.getGcParentId());
                    custom.setGcRelId(children.getGcRelId());
                    custom.setGcName(children.getGcName());
                    custom.setGcPic(children.getGcPic());
                    custom.setGcSort(children.getGcSort());
                    custom.setGcshow(children.getGcshow());
                    custom.setGcTitle(children.getGcTitle());
                    custom.setGcDescription(children.getGcDescription());
                    custom.setGcIdpath(children.getGcIdpath());

                    custom.setGcUrl(children.getGcUrl());
                    custom.setGcAddUser(children.getGcAddUser());
                    custom.setGcUpUser(children.getGcUpUser());
                    custom.setGcAdvid(children.getGcAdvid());
                    custom.setCreateTime(children.getCreateTime());
                    custom.setUpdateTime(children.getUpdateTime());

                    if (!gclzs.contains(custom)) {
                        gclzs.add(custom);
                    }
                }
            }

            // 模板生成菜單的時(shí)候只有兩層旱幼,所以,處理兩層就可以了突委。
            for(GoodsClassCustom custom: gclzs) {
                for(GoodsClassCustom children: allCategoryList) {
                    if(custom.getGcId().equals(children.getGcParentId())) {

                        custom.setHasChild(1);
                        List<GoodsClassCustom> sons;
                        if(null == custom.getClassCustomList()) {
                            sons = new ArrayList<>();
                            custom.setClassCustomList(sons);
                        } else {
                            sons = custom.getClassCustomList();
                        }

                        sons.add(children);
                    }
                }
            }

            for(GoodsClassCustom custom: gclzs) {
                List<GoodsClassCustom> sons = custom.getClassCustomList();
                if(null != sons && sons.size() > 0 ) {
                    for(GoodsClassCustom son: sons) {

                        for(GoodsClassCustom children: allCategoryList) {
                            if(son.getGcId().equals(children.getGcParentId())) {

                                son.setHasChild(1);
                                List<GoodsClassCustom> grandsons;
                                if(null == son.getClassCustomList()) {
                                    grandsons = new ArrayList<>();
                                    son.setClassCustomList(grandsons);
                                } else {
                                    grandsons = son.getClassCustomList();
                                }

                                grandsons.add(children);

                            }
                        }
                    }
                }
            }
        }
        return gclzs;
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末柏卤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子匀油,更是在濱河造成了極大的恐慌缘缚,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敌蚜,死亡現(xiàn)場(chǎng)離奇詭異桥滨,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門齐媒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蒲每,“玉大人,你說(shuō)我怎么就攤上這事喻括⊙樱” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵唬血,是天一觀的道長(zhǎng)望蜡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)拷恨,這世上最難降的妖魔是什么脖律? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮腕侄,結(jié)果婚禮上小泉,老公的妹妹穿的比我還像新娘。我一直安慰自己兜挨,他們只是感情好膏孟,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拌汇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弊决。 梳的紋絲不亂的頭發(fā)上噪舀,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音飘诗,去河邊找鬼与倡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛昆稿,可吹牛的內(nèi)容都是我干的纺座。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼溉潭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼净响!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起喳瓣,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤馋贤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后畏陕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體配乓,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了犹芹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片崎页。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖腰埂,靈堂內(nèi)的尸體忽然破棺而出实昨,到底是詐尸還是另有隱情,我是刑警寧澤盐固,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布荒给,位于F島的核電站,受9級(jí)特大地震影響刁卜,放射性物質(zhì)發(fā)生泄漏志电。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧楞艾,春花似錦滩租、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至魁亦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間羔挡,已是汗流浹背洁奈。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绞灼,地道東北人利术。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像低矮,于是被迫代替她去往敵國(guó)和親印叁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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

  • jHipster - 微服務(wù)搭建 CC_簡(jiǎn)書[http://www.reibang.com/u/be0d56c4...
    quanjj閱讀 816評(píng)論 0 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理军掂,服務(wù)發(fā)現(xiàn)轮蜕,斷路器,智...
    卡卡羅2017閱讀 134,702評(píng)論 18 139
  • 協(xié)同過(guò)濾定義: 基于用戶的行為良姆,利用某興趣相投肠虽、擁有共同經(jīng)驗(yàn)之群體的喜好來(lái)推薦用戶感興趣的信息,個(gè)人通過(guò)合作的機(jī)制...
    pooncheukkei閱讀 391評(píng)論 0 1
  • 各位前輩玛追、各位同仁: 大家好税课!我叫楊漢銀闲延,今年58歲,公務(wù)員韩玩。雖已年近花甲垒玲,2014年7月開始學(xué)寫詩(shī),由于...
    大度做人閱讀 203評(píng)論 1 4
  • 《歡樂頌》的劇情設(shè)計(jì)很簡(jiǎn)單找颓,就是五個(gè)不同家境合愈、不同背景、不同認(rèn)知層級(jí)击狮、不同性格的女孩佛析,扎堆在一起,再加上聞風(fēng)而來(lái)的...
    威樂河灣閱讀 356評(píng)論 0 0