腾讯云SQL优化大赛解析(初赛)

建表

CREATE TABLE `order` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `name` varchar(32) NOT NULL,

  `creator` varchar(24) NOT NULL,

  `price` varchar(64) NOT NULL,

  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

  `status` tinyint(1) not null,

  PRIMARY KEY (`id`)

);


CREATE TABLE `order_item` (

  `id` bigint(20) NOT NULL AUTO_INCREMENT,

  `name` varchar(32) NOT NULL,

  `parent` bigint(20) NOT NULL,

  `status` int not null,

  `type` varchar(12) NOT NULL DEFAULT '0',

  `quantity` int not null default 1,

  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

  PRIMARY KEY (`id`)

);


待优化语句①

SELECT *

FROM  `order` o

      INNER JOIN order_item i ON i.parent = o.id

ORDER  BY o.status ASC,

          i.update_time DESC

LIMIT  0, 20;

o表大约2000数据,i表大约50W行数据


思路

o表的status只有1和0这2种值,分别令status的值=1和=0,分别取前20,再把结果集UNION ALL起来在进行一次排序。

如果不采用这种方式,将会走全表扫描之后再进行2次排序,扫描行数非常多,相当耗时


官方答案

SELECT o.*,i.*

FROM  (

        (SELECT o.id,

            i.id item_id

      FROM  `order` o

            INNER JOIN order_item i

                    ON i.parent =o.id

          WHERE  o.status = 0

          ORDER  BY i.update_time DESC

          LIMIT  0, 20)

          UNION ALL

          (SELECT o.id,

            i.id item_id

          FROM  `order` o

            INNER JOIN order_item i

                    ON i.parent =o.id

          WHERE  o.status = 1

          ORDER  BY i.update_time DESC

          LIMIT  0, 20)

        ) tmp

      INNER JOIN `order` o ON tmp.id = o.id

      INNER JOIN order_item i ON tmp.item_id =i.id

ORDER  BY o.status ASC,

          i.update_time DESC

LIMIT  0, 20;


需添加的索引

alter table order_item add index idx_1(update_time,parent);

alter table `order` add index idx_0(status);



待优化语句②

update `order` set

create_time = now()

where id in (

    select parent from order_item where type = 2

);


该语句第一眼望过去涉及到2个知识点,第一个反应是in改inner join,第二个是临时表内的去重。

按照官方说法,这个语句除了上面的2个知识点外,还有对数据类型的核对,type是一个varchar类型,而临时表的查询直接改变了类型;其次在对临时表的去重过程中,很多人使用了distinct,按照官方说法,临时表的distinct会造成半连接失效,所以这里不能用distinct,而是需要用group by。


需要添加的索引

alter table `order` add index idx_1(type,parent);

语句改写

update `order` o inner join

(select type,parent from`order_item`where type='2' group by type,parent) i 

on o.id = i.parent

set create_time =now();


关于半连接

MySQL半连接



大赛官方解析链接

腾讯云数据库优化初赛

你可能感兴趣的:(腾讯云SQL优化大赛解析(初赛))