记一次sql优化调整

表结构
CREATE TABLE `orderformrookie` (
  `ID` BIGINT(20) NOT NULL,
  `CAINIAO_ID` BIGINT(20) NOT NULL COMMENT 'cainiaowaybilldetail的ID',
  `ORDER_ID` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '订单号',
  `SYSORDER_ID` VARCHAR(50) NOT NULL COMMENT '系统订单号(面单类型+id组成)',
  `BARCODE_ID` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '运单号',
  `SELLER_ID` BIGINT(50) DEFAULT NULL COMMENT '商家ID',
  `SEND_SITE` VARCHAR(50) DEFAULT NULL COMMENT '发件网点',
  `SEND_NAME` VARCHAR(50) DEFAULT NULL COMMENT '发件人',
  `SEND_MOBILE` VARCHAR(255) DEFAULT NULL COMMENT '发件人手机',
  `SEND_ADDRESS` VARCHAR(600) DEFAULT NULL COMMENT '发件人地址',
  `SEND_PROVINCE_NAME` VARCHAR(255) DEFAULT NULL,
  `SEND_CITY_NAME` VARCHAR(255) DEFAULT NULL,
  `SEND_AREA_NAME` VARCHAR(255) DEFAULT NULL,
  `SEND_TOWN_NAME` VARCHAR(255) DEFAULT NULL,
  `SEND_DETAIL_ADDRESS` VARCHAR(512) DEFAULT NULL,
  `RECEIVE_SITE` VARCHAR(50) DEFAULT NULL COMMENT '收件网点',
  `RECEIVE_NAME` VARCHAR(50) DEFAULT NULL COMMENT '收件人姓名',
  `RECEIVE_PHONE` VARCHAR(50) DEFAULT NULL COMMENT '收件人电话',
  `RECEIVE_ADDRESS` VARCHAR(600) DEFAULT NULL COMMENT '收件人地址',
  `RECEIVE_PROVINCE_NAME` VARCHAR(255) DEFAULT NULL,
  `RECEIVE_CITY_NAME` VARCHAR(255) DEFAULT NULL,
  `RECEIVE_AREA_NAME` VARCHAR(255) DEFAULT NULL,
  `RECEIVE_TOWN_NAME` VARCHAR(255) DEFAULT NULL,
  `RECEIVE_DETAIL_ADDRESS` VARCHAR(512) DEFAULT NULL,
  `WEIGHT` BIGINT(20) DEFAULT NULL COMMENT '总重量',
  `VOLUME` BIGINT(20) DEFAULT NULL COMMENT '总体积',
  `REGION_PLACE` VARCHAR(200) DEFAULT NULL COMMENT '大笔',
  `GATHER_PLACE` VARCHAR(200) DEFAULT NULL COMMENT '集包地',
  `CREATE_TIME` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '下单时间',
  `MODIFY_TIME` DATETIME DEFAULT NULL COMMENT '更新时间',
  `ORDER_STATUS` INT(15) DEFAULT '0' COMMENT '订单类型,默认0未处理,-1正常(已有轨迹),1预回收,2已回收',
  `SEND_STATUS` INT(15) DEFAULT '0' COMMENT '是否推送过的 0未推送,1已推送',
  `GIS_STATUS` INT(1) DEFAULT '0' COMMENT '是否发送给gis,0:未发送,1:已发送,2:已接收,状态1是为gis批量接口准备',
  `ORDER_FORM_ITEM` VARCHAR(500) DEFAULT NULL COMMENT '商品信息列表',
  `PRODUCT_NAME` VARCHAR(255) DEFAULT NULL COMMENT '商品名称(只保存第一个订单)',
  `PRODUCT_COUNT` BIGINT(19) DEFAULT NULL COMMENT '商品数量(只保存第一个订单)',
  `TRACK_STATUS` INT(1) DEFAULT '0' COMMENT '运单轨迹状态,0:菜鸟下单,5:揽件,6:运输中,7:签收,8:运单回收',
  `MSG_VERSION` BIGINT(19) DEFAULT NULL COMMENT '面单版本号(消息异常乱序时使用,新消息的版本号大于旧消息)',
  `ACTIVE` INT(15) DEFAULT '1' COMMENT '是否活跃(0:不活跃,1:活跃)',
  `IS_UPDATE` VARCHAR(2) DEFAULT 'N' COMMENT '是否是更新数据(更新数据需走更新补录接口)',
  `RECOVER_TIME` DATETIME DEFAULT NULL COMMENT '回收时间',
  `SITE_WEIGHT` DOUBLE(20,2) DEFAULT '0.00' COMMENT '网点重量',
  `BALANCE_WEIGHT` DOUBLE(20,2) DEFAULT '0.00' COMMENT '结算重量',
  `MATCH_MAP_TYPE` INT(5) DEFAULT '0' COMMENT '网点匹配类型,-1:盲区,无效地址,-11:其他',
  PRIMARY KEY (`ID`,`CREATE_TIME`),
  KEY `UK_BARCODE_ID` (`BARCODE_ID`),
  KEY `ORDER_ID` (`ORDER_ID`) USING BTREE,
  KEY `SEND_STATUS` (`SEND_STATUS`) USING BTREE,
  KEY `TRACK_STATUS` (`TRACK_STATUS`) USING BTREE,
  KEY `INDEX_CREATETIME_SITEID` (`CREATE_TIME`,`SEND_SITE`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='菜鸟订单表'
/*!50100 PARTITION BY RANGE ( TO_DAYS(create_time))
(PARTITION p180515 VALUES LESS THAN (737194) ENGINE = InnoDB,
 PARTITION p180530 VALUES LESS THAN (737209) ENGINE = InnoDB,
 PARTITION p180615 VALUES LESS THAN (737225) ENGINE = InnoDB,
 PARTITION p180630 VALUES LESS THAN (737240) ENGINE = InnoDB,
 PARTITION p180715 VALUES LESS THAN (737255) ENGINE = InnoDB,
 PARTITION p180730 VALUES LESS THAN (737270) ENGINE = InnoDB,
 PARTITION p180815 VALUES LESS THAN (737286) ENGINE = InnoDB,
 PARTITION p180830 VALUES LESS THAN (737301) ENGINE = InnoDB,
 PARTITION p180915 VALUES LESS THAN (737317) ENGINE = InnoDB,
 PARTITION p180930 VALUES LESS THAN (737332) ENGINE = InnoDB,
 PARTITION p181015 VALUES LESS THAN (737347) ENGINE = InnoDB,
 PARTITION p181030 VALUES LESS THAN (737362) ENGINE = InnoDB,
 PARTITION p181115 VALUES LESS THAN (737378) ENGINE = InnoDB,
 PARTITION p181130 VALUES LESS THAN (737393) ENGINE = InnoDB,
 PARTITION p181215 VALUES LESS THAN (737408) ENGINE = InnoDB,
 PARTITION p181230 VALUES LESS THAN (737423) ENGINE = InnoDB,
 PARTITION pMax VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
SQL脚本:
SELECT t1.id,
            t1.order_id,
            t1.sysorder_id,
            t1.barcode_id,
            t1.seller_id,
            t1.send_site,
            t1.send_name,
            t1.send_mobile,
            t1.send_address,
            t1.receive_site,
            t1.receive_name,
            t1.receive_phone,
            t1.receive_address,
            t1.region_place,
            t1.gather_place,
            t1.create_time,
            t1.active,
            t1.track_status,
            t3.client_name,
            t3.client_encode,
            t3.site_name AS sendsitename,
            t4.first_center_site_name,
            t4.org_name AS receivesitename FROM
                (SELECT id,
                order_id,
                sysorder_id,
                barcode_id,
                seller_id,
                send_site,
                send_name,
                send_mobile,
                send_address,
                receive_site,
                receive_name,
                receive_phone,
                receive_address,
                region_place,
                gather_place,
                create_time,
                active,
                track_status
                FROM
                orderformrookie
                WHERE
                    CREATE_TIME >= '2018-08-01 00:00:00' AND CREATE_TIME <= '2018-08-02 23:59:59'
                     AND SEND_SITE = '15992'
                ) t1
        LEFT JOIN  (
        SELECT DISTINCT (b.USER_ID),b.BUSINESS_CODE,b.SITE_ID FROM businesses b
        WHERE (b.STATE = 1 OR b.STATE = 4) AND b.SITE_ID = 15992
        ) t2 ON t1.SELLER_ID = t2.BUSINESS_CODE AND t1.SEND_SITE = t2.SITE_ID
        LEFT JOIN sysuser t3 ON t2.USER_ID=t3.ID
        LEFT JOIN siteinfo t4 ON t1.RECEIVE_SITE = t4.BIZ_ID AND t4.STATE=1
        ORDER BY t1.id DESC
explain结果:

这里写图片描述

执行结果:

这里写图片描述

解决方法:

首先强制使用索引
这里写图片描述
这里写图片描述
似乎好了一些,个人认为应该还有优化的空间。

继续优化,如果单独使用createtime字段条件的话,非常快,因为create_time是分区键值:
这里写图片描述
如果加上site_id条件则立马性能下来了。
这里写图片描述

再继续进行调整,为site_id单独加一个索引:
ALTER TABLE orderformrookie ADD INDEX idx_send_site (SEND_SITE);
重新执行sql的执行计划
这里写图片描述
直接用到索引定位数据,再执行一下sql:
这里写图片描述
到此,优化完成,然后删除无用索引
ALTER TABLE orderformrookie DROP INDEX INDEX_CREATETIME_SITEID;

总结:

使用分区表,分区键不需要单独建立索引,直接通过分区键来检索的话,速度非常快,但是当如果加入另一个条件进行检索的话,如果没有索引,则仍然会进行全表扫描操作,故此单独为该条件字段加一个索引,在sql中就会直接引用了。因为这个表是前几天从普通标改为分区表的,当时这个索引INDEX_CREATETIME_SITEID是普通表里使用的,当表变成分区表的时候,那么这个索引就属于废弃索引,不能被使用了,需要重新创建一个索引即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值