基于pg_qualstats和hypopg的自动索引调优
pg-qualstats的安装和配置
1.安装pg-qualstats
sudo apt install postgresql--pg-qualstats
2.将pg_qualstats和pg_stat_statements添加到shared_preload_libraries,使得postgresql .conf文件中具有以下设置:
shared_preload_libraries = 'pg_stat_statements,pg_qualstats' # (change requires restart)
postgresql.conf文件在/etc/postgresql/10/main/目录下
执行grep 'shared_preload' postgresql.conf查看

3.重新启动PG。
service postgresql restart
4.进入PG
sudo su - postgres psql
5.查询shared_preload_libraries
show shared_preload_libraries ;

Hypopg的安装和配置
1.安装 hypopg
apt install postgresql-server-dev- apt install postgresql--hypopg
自动索引调优
1.进入PG
sudo su - postgres
2.设置采样率 pg_qualstats .sample_rate1,保证调参涉及到所有的query
psql -d postgres -c "ALTER SYSTEM SET pg_qualstats.sample_rate TO 1"
验证
psql -c "select pg_reload_conf()"
3.进入PG
psql
4.加载extension
CREATE EXTENSION hypopg; CREATE EXTENSION pg_stat_statements ; CREATE EXTENSION pg_qualstats;
5.查看配置
\dx show shared_preload_libraries ;
6.建立测试数据库
create database testdb owner postgres;
7.复现样例测试
建表
CREATE TABLE test (id int, dept int, id2 int, id3 int, id4 int, id5 int,id6 int,id7 int,details text, zipcode int);
插入数据
INSERT INTO test SELECT (random() * 1000000)::int, (random() * 1000000)::int, (random() * 1000000)::int,(random() * 1000000)::int,(random() * 1000000)::int,(random() * 1000000)::int,(random() * 1000000)::int,(random() * 1000000)::int, md5(g::text), floor(random()* (20000-9999 + 1) + 9999) FROM generate_series(1,1*1e6) g;
执行workload
select * from test where id2 = 1 and id4 = 3; select * from test where id3 = 3; select * from test where id3 = 3 and id4 = 2; select * from test where id4 = 2 and id2 = 3;
建立函数 find_usable_indexes
CREATE OR REPLACE FUNCTION find_usable_indexes()
RETURNS VOID AS
$$
DECLARE
l_queries record;
l_querytext text;
l_idx_def text;
l_bef_exp text;
l_after_exp text;
hypo_idx record;
l_attr record;
/* l_err int; */
BEGIN
CREATE TABLE IF NOT EXISTS public.idx_recommendations (queryid bigint,
query text, current_plan jsonb, recmnded_index text, hypo_plan jsonb);
FOR l_queries IN
SELECT t.relid, t.relname, t.queryid, t.attnames, t.attnums,
pg_qualstats_example_query(t.queryid) as query
FROM
(
SELECT qs.relid::regclass AS relname, qs.relid AS relid, qs.queryid,
string_agg(DISTINCT attnames.attnames,',') AS attnames, qs.attnums
FROM pg_qualstats_all qs
JOIN pg_qualstats q ON q.queryid = qs.queryid
JOIN pg_stat_statements ps ON q.queryid = ps.queryid
JOIN pg_amop amop ON amop.amopopr = qs.opno
JOIN pg_am ON amop.amopmethod = pg_am.oid,
LATERAL
(
SELECT pg_attribute.attname AS attnames
FROM pg_attribute
JOIN unnest(qs.attnums) a(a) ON a.a = pg_attribute.attnum
AND pg_attribute.attrelid = qs.relid
ORDER BY pg_attribute.attnum) attnames,
LATERAL unnest(qs.attnums) attnum(attnum)
WHERE NOT
(
EXISTS
(
SELECT 1
FROM pg_index i
WHERE i.indrelid = qs.relid AND
(arraycontains((i.indkey::integer[])[0:array_length(qs.attnums, 1) - 1],
qs.attnums::integer[]) OR arraycontains(qs.attnums::integer[],
(i.indkey::integer[])[0:array_length(i.indkey, 1) + 1]) AND i.indisunique)))
GROUP BY qs.relid, qs.queryid, qs.qualnodeid, qs.attnums) t
GROUP BY t.relid, t.relname, t.queryid, t.attnames, t.attnums
LOOP
/* RAISE NOTICE '% : is queryid',l_queries.queryid; */
execute 'explain (FORMAT JSON) '||l_queries.query INTO l_bef_exp;
execute 'select hypopg_reset()';
execute 'SELECT indexrelid,indexname FROM hypopg_create_index(''CREATE INDEX on '||l_queries.relname||'('||l_queries.attnames||')'')' INTO hypo_idx;
execute 'explain (FORMAT JSON) '||l_queries.query INTO l_after_exp;
execute 'select hypopg_get_indexdef('||hypo_idx.indexrelid||')' INTO l_idx_def;
INSERT INTO public.idx_recommendations (queryid,query,current_plan,recmnded_index,hypo_plan)
VALUES (l_queries.queryid,l_querytext,l_bef_exp::jsonb,l_idx_def,l_after_exp::jsonb);
END LOOP;
execute 'select hypopg_reset()';
END;
$$ LANGUAGE plpgsql;
执行函数find_usable_indexes
select find_usable_indexes();
查找索引
select queryid, current_plan->0->'Plan'->>'Total Cost' as "cost_without_index", hypo_plan->0->'Plan'->>'Total Cost' as "cost_with_index", round((((current_plan->0->'Plan'->>'Total Cost')::numeric-(hypo_plan->0->'Plan'->>'Total Cost')::numeric)*100/(current_plan->0->'Plan'->>'Total Cost')::numeric),2) as percent_improvd FROM idx_recommendations order by 4 desc;
select b.query, a.recmnded_index,round((((a.current_plan->0->'Plan'->>'Total Cost')::numeric-(hypo_plan->0->'Plan'->>'Total Cost')::numeric)*100/(a.current_plan->0->'Plan'->>'Total Cost')::numeric),2) as percent_improvd FROM idx_recommendations a JOIN pg_stat_statements b ON a.queryid = b.queryid WHERE round((((current_plan->0->'Plan'->>'Total Cost')::numeric-(hypo_plan->0->'Plan'->>'Total Cost')::numeric)*100/(current_plan->0->'Plan'->>'Total Cost')::numeric),2) > 0 order by 3 desc ;
基于pg_qualstats和hypopg的自动索引调优的更多相关文章
- OCM_第十四天课程:Section6 —》数据库性能调优_各类索引 /调优工具使用/SQL 优化建议
注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...
- 11g新特性-自动sql调优(Automatic SQL Tuning)
11g新特性-自动sql调优(Automatic SQL Tuning) 在Oracle 10g中,引进了自动sql调优特性.此外,ADDM也会监控捕获高负载的sql语句. 在Oracle 11g中, ...
- SQL Server调优系列进阶篇(如何索引调优)
前言 上一篇我们分析了数据库中的统计信息的作用,我们已经了解了数据库如何通过统计信息来掌控数据库中各个表的内容分布.不清楚的童鞋可以点击参考. 作为调优系列的文章,数据库的索引肯定是不能少的了,所以本 ...
- SQL Server调优系列进阶篇 - 如何索引调优
前言 上一篇我们分析了数据库中的统计信息的作用,我们已经了解了数据库如何通过统计信息来掌控数据库中各个表的内容分布.不清楚的童鞋可以点击参考. 作为调优系列的文章,数据库的索引肯定是不能少的了,所以本 ...
- SQL Server 调优系列进阶篇 - 如何索引调优
前言 上一篇我们分析了数据库中的统计信息的作用,我们已经了解了数据库如何通过统计信息来掌控数据库中各个表的内容分布.不清楚的童鞋可以点击参考. 作为调优系列的文章,数据库的索引肯定是不能少的了,所以本 ...
- MySQL索引调优【转】
一.关于查询计划 其实,关于所有的关系型数据库中,在运行T-SQL语句的时候,在查询器进行编译运行的同时,都会有着自己的内部的一个优化过程,而这优化之后的产物就是:执行计划. 在SQL SERVER中 ...
- Mysql的索引调优详解:如何去创建索引以及避免索引失效
在正式介绍Mysql调优之前,先补充mysql的两种引擎 mysql逻辑分层 InnoDB:事务优先(适合高并发操作,行锁) MyISAM:性能优先(表锁) 查看使用的引擎: show variabl ...
- mysql数据库索引调优
一.mysql索引 1.磁盘文件结构 innodb引擎:frm格式文件存储表结构,ibd格式文件存储索引和数据. MyISAM引擎:frm格式文件存储表结构,MYI格式文件存储索引,MYD格式文件存储 ...
- 必读,sql加索引调优案例和explain extended说明
做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 昨天分享了Mysql中的 explain 命令,使用 explain 来分析 select 语句的运行效果,如 :expl ...
随机推荐
- views 视图层
Django的View(视图) 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误, ...
- [转帖]Nginx rewrite 规则 与 proxy_pass 实现
Nginx rewrite 规则 与 proxy_pass 实现 https://www.cnblogs.com/jicki/p/5546916.html Nginx rewrite 规则 与 pr ...
- [#] - .Net平台的实时性能监控
App Metricshttps://www.app-metrics.io ASP.NET Core之跨平台的实时性能监控http://www.cnblogs.com/GuZhenYin/p/7170 ...
- 《Mysql - 读写分离有哪些坑?》
一:读写分离 - 概念 - 读写分离的主要目标就是分摊主库的压力. - 基本架构 - - 二:两种读写分离的架构特点 - 客户端直连方案 - 因为少了一层 proxy 转发,所以查询性能稍 ...
- Python中关于Lambda函数的使用总结
lambda表达式是一种匿名函数,对应python中的自定义函数def,是定义某个函数时比较高级的一种写法.作为python初学者,本文整理了lambda的一些基本用法和特点. lambda和def的 ...
- PAT(B) 1054 求平均值(Java)
题目链接:1054 求平均值 (20 point(s)) 题目描述 本题的基本要求非常简单:给定 N 个实数,计算它们的平均值.但复杂的是有些输入数据可能是非法的.一个"合法"的输 ...
- vs2017环境下python包的安装
1)---vs已经下载了的才适用 1,鼠标放在右侧窗口python环境那里(如没有窗口,可点击最上方的“窗口”-“重置窗口”) 2,右键然后点击“查看所有python环境”,会弹出当前默认的环境(高亮 ...
- Luogu3824 [NOI2017]泳池 【多项式取模】【递推】【矩阵快速幂】
题目分析: 用数论分块的思想,就会发现其实就是连续一段的长度$i$的高度不能超过$\lfloor \frac{k}{i} \rfloor$,然后我们会发现最长的非$0$一段不会超过$k$,所以我们可以 ...
- Spring Boot学习随记
由于早年在管理领域耕耘了一段时间,完美错过了Spring的活跃期, 多少对这个经典的技术带有一种遗憾的心态在里面的, 从下面的我的生涯手绘图中大概可以看出来我的经历. 最近由于新介入到了工业数字化领域 ...
- 如何录屏做GIF图
网上找了一下,ScreenToGif 这个神器 https://github.com/NickeManarin/ScreenToGif https://github.com/NickeManarin/ ...