索引優(yōu)化通常需要依賴(lài)運(yùn)維或開(kāi)發(fā)人員對(duì)數(shù)據(jù)庫(kù)引擎內(nèi)部?jī)?yōu)化和執(zhí)行原理的深入理解。為優(yōu)化體驗(yàn)和降低操作門(mén)檻,PolarDB-X 1.0推出了基于代價(jià)優(yōu)化器的索引推薦功能,可根據(jù)查詢(xún)語(yǔ)句分析并推薦索引,幫助您降低查詢(xún)耗時(shí),提升數(shù)據(jù)庫(kù)性能。
注意事項(xiàng)
索引推薦功能僅針對(duì)您當(dāng)前指定的SQL查詢(xún)語(yǔ)句進(jìn)行分析與推薦。在根據(jù)推薦的信息創(chuàng)建索引前,您需要評(píng)估創(chuàng)建該索引對(duì)其它查詢(xún)的影響。
環(huán)境說(shuō)明
TPC-H是業(yè)界常用的基準(zhǔn)測(cè)試方法,由TPC委員會(huì)制定發(fā)布,用于評(píng)測(cè)數(shù)據(jù)庫(kù)的分析型查詢(xún)能力。TPC-H基準(zhǔn)測(cè)試方法包含8張數(shù)據(jù)表、22條復(fù)雜的SQL查詢(xún)(即Q1~Q22)。下圖為執(zhí)行TPC-H中的Q17(小訂單收入查詢(xún))的返回信息,可查看到執(zhí)行該查詢(xún)語(yǔ)句消耗的時(shí)間為28.76秒。本文將通過(guò)智能索引推薦功能,優(yōu)化該查詢(xún)語(yǔ)句的執(zhí)行效率。
本文的TPC-H的實(shí)現(xiàn)基于TPC-H的基準(zhǔn)測(cè)試,并不能與已發(fā)布的TPC-H基準(zhǔn)測(cè)試結(jié)果相比較,本文中的測(cè)試并不符合TPC-H基準(zhǔn)測(cè)試的所有要求。
步驟一:查詢(xún)智能索引推薦信息
如需查詢(xún)某個(gè)查詢(xún)語(yǔ)句的智能索引推薦信息,您只需在該查詢(xún)語(yǔ)句前增加EXPLAIN ADVISOR命令,示例如下:
EXPLAIN ADVISOR
SELECT sum(l_extendedprice) / 7.0 AS avg_yearly
FROM lineitem,
part
WHERE p_partkey = l_partkey
AND p_brand = 'Brand#23'
AND p_container = 'MED BOX'
AND l_quantity <
(SELECT 0.2 * avg(`l_quantity`)
FROM lineitem
WHERE l_partkey = p_partkey);
執(zhí)行上述命令后,PolarDB-X 1.0將返回推薦的索引創(chuàng)建語(yǔ)句、添加索引前后的代價(jià)等信息,詳細(xì)的返回信息及其注釋如下所示:
- 本案例中,預(yù)計(jì)磁盤(pán)I/O提升百分比為3024.7%,表明使用推薦的索引將帶來(lái)較大的收益。
- 當(dāng)PolarDB-X 1.0無(wú)法推薦索引時(shí),返回信息中會(huì)建議您在業(yè)務(wù)低峰期,對(duì)目標(biāo)表執(zhí)行Analyze Table命令刷新統(tǒng)計(jì)信息(該操作會(huì)消耗較大的I/O資源)。當(dāng)統(tǒng)計(jì)信息更新后,再次執(zhí)行索引推薦可獲得更準(zhǔn)確的索引。
IMPROVE_VALUE: 2465.3% # 預(yù)計(jì)綜合代價(jià)提升百分比
IMPROVE_CPU: 59377.4% # 預(yù)計(jì)CPU提升百分比
IMPROVE_MEM: 0.4% # 預(yù)計(jì)內(nèi)存提升百分比
IMPROVE_IO: 3024.7% # 預(yù)計(jì)磁盤(pán)I/O提升百分比
IMPROVE_NET: 2011.1% # 預(yù)計(jì)網(wǎng)絡(luò)傳輸提升百分比
BEFORE_VALUE: 4.711359845E8 # 添加索引前綜合代價(jià)值
BEFORE_CPU: 1.19405577E7 # 添加索引前CPU估算值
BEFORE_MEM: 426811.2 # 添加索引前內(nèi)存消耗估算值
BEFORE_IO: 44339 # 添加索引前磁盤(pán)I/O估算值
BEFORE_NET: 47.5 # 添加索引前網(wǎng)絡(luò)傳輸估算值
AFTER_VALUE: 1.83655008E7 # 添加索引后綜合代價(jià)值
AFTER_CPU: 20075.8 # 添加索引后CPU估算值
AFTER_MEM: 425016 # 添加索引后內(nèi)存消耗估算值
AFTER_IO: 1419 # 添加索引后磁盤(pán)I/O估算值
AFTER_NET: 2.2 # 添加索引后網(wǎng)絡(luò)傳輸估算值
ADVISE_INDEX: ALTER TABLE `lineitem` ADD INDEX `__advise_index_lineiteml_partkey`(`l_partkey`);
/* ADVISE_INDEX中的內(nèi)容為推薦的索引創(chuàng)建語(yǔ)句 */
NEW_PLAN: # 添加索引后預(yù)計(jì)執(zhí)行計(jì)劃
Project(avg_yearly="$f0 / ?0")
HashAgg($f0="SUM(l_extendedprice)")
Filter(condition="l_quantity < $16 * f17w0$o0")
SortWindow(p_partkey="p_partkey", l_partkey="l_partkey", l_quantity="l_quantity", l_extendedprice="l_extendedprice", $16="$16", f5w0$o0="window#0AVG($2)", Reference Windows="window#0=window(partition {1} order by [] range between UNBOUNDED PRECEDING and UNBOUNDED PRECEDING aggs [AVG($2)])")
MemSort(sort="l_partkey ASC")
BKAJoin(condition="l_partkey = p_partkey", type="inner")
Gather(concurrent=true)
LogicalView(tables="[0000,0001].part", shardCount=2, sql="SELECT `p_partkey` FROM `part` AS `part` WHERE ((`p_brand` = ?) AND (`p_container` = ?))")
Gather(concurrent=true)
LogicalView(tables="[0000,0001].lineitem", shardCount=2, sql="SELECT `l_partkey`, `l_quantity`, `l_extendedprice`, ? AS `$16` FROM `lineitem` AS `lineitem` WHERE (`l_partkey` IN (...))")
INFO: LOCAL_INDEX # 其它信息