直接上干货:
数据量:50万
mysql版本:5.6.26
表结构:
CREATE TABLE bet_order_product (
bet_order_product_id varchar(40) NOT NULL COMMENT '订单与商品关联id',
bet_order_product_order_id varchar(40) DEFAULT NULL COMMENT '订单主键id',
bet_order_product_order_number varchar(40) DEFAULT NULL COMMENT '订单号',
bet_order_product_product_id varchar(40) DEFAULT NULL COMMENT '商品主键id',
bet_order_product_product_name varchar(40) DEFAULT NULL COMMENT '商品名',
bet_order_product_product_type_id varchar(40) DEFAULT NULL COMMENT '商品类型外键',
bet_order_product_product_count varchar(10) DEFAULT NULL COMMENT '商品数量',
bet_order_product_product_unit_name varchar(20) DEFAULT NULL COMMENT '商品单位名',
bet_order_product_create_time varchar(20) DEFAULT NULL COMMENT '订单与商品关联创建时间',
bet_order_product_update_time timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '订单与商品关联更新时间',
bet_order_product_product_former_price decimal(20,2) DEFAULT NULL COMMENT '商品原标价',
bet_order_product_product_sale_price decimal(20,2) DEFAULT NULL COMMENT '商品时间成交价',
bet_order_product_product_total decimal(20,2) DEFAULT NULL COMMENT '本次订单商品的总价',
bet_order_product_univalent_remark varchar(255) DEFAULT NULL COMMENT '商品单价修改备注',
bet_order_product_del_flag int(2) DEFAULT '1' COMMENT '订单与商品关联删除标记,1、未删除,2、已删除',
bet_order_product_product_bid_price decimal(20,2) DEFAULT '0.00' COMMENT '商品的进价',
PRIMARY KEY (bet_order_product_id),
KEY 商品外键 (bet_order_product_product_id) USING BTREE,
KEY 订单号 (bet_order_product_order_number) USING BTREE,
KEY 订单外键 (bet_order_product_order_id) USING BTREE,
KEY 商品名 (bet_order_product_product_name) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单与商品多对多关联中间表';
原始sql (查询时间:约81s):
select
bet_order_product_order_number,
bet_order_product_product_id,
bet_order_product_product_former_price,
bet_order_product_product_name,
bet_order_product_product_unit_name
from bet_order_product
where bet_order_product_order_number in (123192648142,122219077460,122176172325)
and bet_order_product_del_flag = 1
group by bet_order_product_product_id
优化后sql (约3s):
select
bet_order_product_order_number,
bet_order_product_product_id,
bet_order_product_product_former_price,
bet_order_product_product_name,
bet_order_product_product_unit_name
from (
select
bet_order_product_order_number,
bet_order_product_product_id,
bet_order_product_product_former_price,
bet_order_product_product_name,
bet_order_product_product_unit_name
from bet_order_product
where bet_order_product_order_number in (123192648142,122219077460,122176172325)
and bet_order_product_del_flag = 1
)t
group by bet_order_product_product_id
优化原理:
在分组查询之前先查出数据放在临时表里面,然后在临时表里面去进行数据的分组。
分析:
只查询不分组(时间约3s):
select
bet_order_product_order_number,
bet_order_product_product_id,
bet_order_product_product_former_price,
bet_order_product_product_name,
bet_order_product_product_unit_name
from bet_order_product
where bet_order_product_order_number in (123192648142,122219077460,122176172325)
and bet_order_product_del_flag = 1
查询再分组,执行时间一下就标到了81s左右。
由此得出:问题一定是出在分组(group by)上面。
在网上查阅资料后得出一下结论:
group by:会进行全表的扫描,然后出结果,无论你前面的条件是如何的,它都会去全表扫描一次。
所以:现在直接先查出数据,放在临时表里面,然后再用分组语句去查临时表,这样就能把group by的扫描范围缩小到一定的数据量,而不用再去50万的数据里面去扫描。
优化之路且漫长,祝大家一路顺风。忠告:多去看下官方文档,网上好多资料都是不准确的,坑太多。
BIllZhang