騰訊云SQL優(yōu)化大賽解析(初賽)

建表

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`)

);


待優(yōu)化語句①

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數(shù)據(jù),i表大約50W行數(shù)據(jù)


思路

o表的status只有1和0這2種值,分別令status的值=1和=0,分別取前20,再把結(jié)果集UNION ALL起來在進(jìn)行一次排序。

如果不采用這種方式,將會(huì)走全表掃描之后再進(jìn)行2次排序,掃描行數(shù)非常多,相當(dāng)耗時(shí)


官方答案

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);



待優(yōu)化語句②

update `order` set

create_time = now()

where id in (

? ? select parent from order_item where type = 2

);


該語句第一眼望過去涉及到2個(gè)知識(shí)點(diǎn),第一個(gè)反應(yīng)是in改inner join,第二個(gè)是臨時(shí)表內(nèi)的去重。

按照官方說法,這個(gè)語句除了上面的2個(gè)知識(shí)點(diǎn)外,還有對(duì)數(shù)據(jù)類型的核對(duì),type是一個(gè)varchar類型,而臨時(shí)表的查詢直接改變了類型;其次在對(duì)臨時(shí)表的去重過程中,很多人使用了distinct,按照官方說法,臨時(shí)表的distinct會(huì)造成半連接失效,所以這里不能用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();


關(guān)于半連接

MySQL半連接



大賽官方解析鏈接

騰訊云數(shù)據(jù)庫(kù)優(yōu)化初賽

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容