Index-advisor是openGauss2.1.0中的一个工具,可以帮助用户分析数据库中的查询语句,推荐最佳的索引策略。使用Index-advisor可以提高查询性能,减少数据库的负载。
下面是利用Index-advisor实现索引推荐的具体步骤:
安装Index-advisor
如果不是源码安装openGauss,而是使用编译好的openGauss安装包安装,则X-Tuner是openGauss2.1.0自带的一款工具。在安装openGauss2.1.0时,X-Tuner也会被一同安装。具体安装可以参考:【基于openEuler上安装单机openGauss2.1.0企业版】
如果是源码安装,则需要单独安装Index-advisor,可参考:【基于openEuler 20.03 和openGauss2.1.0环境中安装X-Tuner】
本文是基于这种方式进行测试
参数调优前,使用【omm
用户】先执行TPCH脚本queries.sql(该文件是在【openGauss2.1.0 TPC-C数据导入】产生的),记录下脚本执行时间,这个过程可能需要花费十多分钟的时间,请耐心等待。
[omm@sjmopengauss01 queries]$ gsql -d tpch -p 5432 -r -f /opt/software/tpch-kit/dbgen/queries/queries.sql > /opt/software/tpch-kit/dbgen/queries/queries01.log
执行结束后,查看queries01.log:
tail -10 /opt/software/tpch-kit/dbgen/queries/queries01.log
结果如下:
……
total time: 1190160 ms
登录数据库
切换到【omm
用户】,执行如下命令:
[omm@sjmopengauss01 data]$ gsql -d tpch -p 5432 -r
使用SQL查询2020年3月订单收入,并进行排序,执行结果如下:
SELECT ad.province AS province, SUM(o.actual_price) AS GMV
FROM litemall_orders o,
address_dimension ad,
date_dimension dd
WHERE o.address_key = ad.address_key
AND o.add_date = dd.date_key
AND dd.year = 2020
AND dd.month = 3
GROUP BY ad.province
ORDER BY SUM(o.actual_price) DESC;
结果如下:
province | gmv
------------------+-------------
上海市 | 13927163.00
江苏省 | 13900815.00
浙江省 | 13890720.00
天津市 | 13750598.00
北京市 | 13458554.00
山东省 | 4381747.00
重庆市 | 4172788.00
福建省 | 4005384.00
安徽省 | 3973989.00
广东省 | 3842252.00
河南省 | 1130277.00
海南省 | 1113236.00
新疆维吾尔自治区 | 1058210.00
云南省 | 1041797.00
西藏自治区 | 1040002.00
贵州省 | 1003301.00
吉林省 | 1002830.00
辽宁省 | 982522.00
宁夏回族自治区 | 885719.00
陕西省 | 863598.00
河北省 | 814762.00
广西壮族自治区 | 812580.00
黑龙江省 | 787436.00
湖北省 | 775761.00
湖南省 | 762020.00
江西省 | 753550.00
青海省 | 739701.00
甘肃省 | 734090.00
四川省 | 726917.00
内蒙古自治区 | 667131.00
山西省 | 643208.00
(31 rows)
使用explain
,对该SQL加以分析:
EXPLAIN
SELECT ad.province AS province, SUM(o.actual_price) AS GMV
FROM litemall_orders o,
address_dimension ad,
date_dimension dd
WHERE o.address_key = ad.address_key
AND o.add_date = dd.date_key
AND dd.year = 2020
AND dd.month = 3
GROUP BY ad.province
ORDER BY SUM(o.actual_price) DESC;
执行结果如下:
QUERY PLAN
--------------------------------------------------------------
Sort (cost=4593.80..4593.88 rows=31 width=47)
Sort Key: (sum(o.actual_price)) DESC
-> HashAggregate (cost=4592.72..4593.03 rows=31 width=47)
Group By Key: ad.province
-> Hash Join (cost=4354.43..4585.97 rows=1351 width=15)
Hash Cond: (ad.address_key = o.address_key)
-> Seq Scan on address_dimension ad (cost=0.00..188.02 rows=8002 width=14)
-> Hash (cost=4337.54..4337.54 rows=1351 width=9)
-> Hash Join (cost=1031.78..4337.54 rows=1351 width=9)
Hash Cond: (o.add_date = dd.date_key)
-> Seq Scan on litemall_orders o (cost=0.00..3041.00 rows=100000 width=13)
-> Hash (cost=1031.76..1031.76 rows=2 width=4)
-> Seq Scan on date_dimension dd (cost=0.00..1031.76 rows=2 width=4)
Filter: ((year = 2020) AND ((month)::bigint = 3))
(14 rows)
使用索引推荐功能,对查询语句进行推荐:
select * from gs_index_advise('
SELECT ad.province AS province, SUM(o.actual_price) AS GMV
FROM litemall_orders o,
address_dimension ad,
date_dimension dd
WHERE o.address_key = ad.address_key
AND o.add_date = dd.date_key
AND dd.year = 2020
AND dd.month = 3
GROUP BY ad.province
ORDER BY SUM(o.actual_price) DESC');
结果如下:
schema | table | column
--------+-------------------+------------------------
public | litemall_orders | (address_key,add_date)
public | address_dimension |
public | date_dimension | (year)
(3 rows)
在litemall_orders和date_dimension表上创建虚拟索引列:
select * from hypopg_create_index('create index on litemall_orders(address_key,add_date)');
select * from hypopg_create_index('create index on date_dimension(year)');
执行结果如下:
tpch=# select * from hypopg_create_index('create index on litemall_orders(address_key,add_date)');
indexrelid | indexname
------------+---------------------------------------------------
16648 | <16648>btree_litemall_orders_address_key_add_date
(1 row)
tpch=# select * from hypopg_create_index('create index on date_dimension(year)');
indexrelid | indexname
------------+----------------------------------
16649 | <16649>btree_date_dimension_year
(1 row)
查看创建的虚拟索引列:
select * from hypopg_display_index();
执行结果:
tpch=# select * from hypopg_display_index();
indexname | indexrelid | table | column
---------------------------------------------------+------------+-----------------+-------------------------
<16648>btree_litemall_orders_address_key_add_date | 16648 | litemall_orders | (address_key, add_date)
<16649>btree_date_dimension_year | 16649 | date_dimension | (year)
(2 rows)
获取索引虚拟列大小结果(单位为:字节):
select * from hypopg_estimate_size(16648);
elect * from hypopg_estimate_size(16649);
执行结果:
tpch=# select * from hypopg_estimate_size(16648);
hypopg_estimate_size
----------------------
4177920
(1 row)
tpch=# select * from hypopg_estimate_size(16649);
hypopg_estimate_size
----------------------
696320
(1 row)
开启GUC参数enable_hypo_index:
set enable_hypo_index = on;
注意
:该参数控制数据库的优化器进行EXPLAIN时是否考虑创建的虚拟索引。通过对特定的查询语句执行explain,用户可根据优化器给出的执行计划评估该索引是否能够提升该查询语句的执行效率。
再次使用explain,对该SQL加以分析:
EXPLAIN
SELECT ad.province AS province, SUM(o.actual_price) AS GMV
FROM litemall_orders o,
address_dimension ad,
date_dimension dd
WHERE o.address_key = ad.address_key
AND o.add_date = dd.date_key
AND dd.year = 2020
AND dd.month = 3
GROUP BY ad.province
ORDER BY SUM(o.actual_price) DESC;
等待执行完毕,查看queries02.log:
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=3579.58..3579.65 rows=31 width=47)
Sort Key: (sum(o.actual_price)) DESC
-> HashAggregate (cost=3578.50..3578.81 rows=31 width=47)
Group By Key: ad.province
-> Hash Join (cost=3340.21..3571.74 rows=1351 width=15)
Hash Cond: (ad.address_key = o.address_key)
-> Seq Scan on address_dimension ad (cost=0.00..188.02 rows=8002 width=14)
-> Hash (cost=3323.32..3323.32 rows=1351 width=9)
-> Hash Join (cost=17.56..3323.32 rows=1351 width=9)
Hash Cond: (o.add_date = dd.date_key)
-> Seq Scan on litemall_orders o (cost=0.00..3041.00 rows=100000 width=13)
-> Hash (cost=17.53..17.53 rows=2 width=4)
-> Index Scan using <16649>btree_date_dimension_year on date_dimension dd (cost=0.00..17.53 rows=2 width=4)
Index Cond: (year = 2020)
Filter: ((month)::bigint = 3)
(15 rows)
删除某一个索引虚拟列:
select * from hypopg_drop_index(16648);
其中16648
是前面查看到的indexrelid,执行结果如下:
tpch=# select * from hypopg_drop_index(16648);
hypopg_drop_index
-------------------
t
(1 row)
删除所有索引虚拟列:
select * from hypopg_reset_index();
结果:
tpch=# select * from hypopg_reset_index();
hypopg_reset_index
--------------------
(1 row)
查看索引虚拟列:
select * from hypopg_display_index();
执行结果:
tpch=# select * from hypopg_display_index();
indexname | indexrelid | table | column
-----------+------------+-------+--------
(0 rows)
针对执行的queries.sql进行优化,为customer、order、part表增加主键索引,读者也可以针对queries.sql中的查询内容进行进一步优化。
ALTER TABLE "public"."customer" ADD CONSTRAINT "pk_customer" PRIMARY KEY ("c_custkey");
ALTER TABLE "public"."orders" ADD CONSTRAINT "pk_orders" PRIMARY KEY ("o_orderkey");
ALTER TABLE "public"."part" ADD CONSTRAINT "pk_part" PRIMARY KEY ("p_partkey");
在order表的o_orderdate列,以及lineitem表的l_shipdate列上创建索引,可以通过分析queries.sql查询,进行更深入的优化:
CREATE INDEX idx_o_orderdate ON orders(o_orderdate);
CREATE INDEX idx_l_shipdate ON lineitem(l_shipdate);
重新执行queries.sql查询,执行如下命令:
[omm@sjmopengauss01 data]$ gsql -d tpch -p 5432 -r -f /opt/software/tpch-kit/dbgen/queries/queries.sql > /opt/software/tpch-kit/dbgen/queries/queries03.log
等待执行完毕,查看queries03.log:
tail -10 /opt/software/tpch-kit/dbgen/queries/queries03.log
结果如下:
……
total time:332769
ms
比未进行参数调优时耗时少了857391 ms
,即14.28985
分钟时间。如果系统要求性能较高,在高并发和大业务量的场景下,引入索引大大缩短了响应时间,从整体上看,性能还是有很大的提升。
由此,可以看出,总时长比调优前少许多,说明本次的Index-advisor索引推荐是可取的。
总之,openGauss2.1.0利用Index-advisor进行索引推荐可以有效提高其性能,使其更加适合企业级数据管理。