基于pg_qualstats和hypopg的自动索引调优
时间:2019-11-06
本文章向大家介绍基于pg_qualstats和hypopg的自动索引调优,主要包括基于pg_qualstats和hypopg的自动索引调优使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
pg-qualstats的安装和配置
1.安装pg-qualstats
sudo apt install postgresql-10-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-10 apt install postgresql-10-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 ;
原文地址:https://www.cnblogs.com/xueqiuqiu/p/11805033.html
- sqoop 常用命令整理(二)
- oozie 重新提交作业
- Hbase 学习(十一)使用hive往hbase当中导入数据
- WF追忆
- OpenCV和SVM分类器在自动驾驶中的车辆检测
- Hive Tunning(三) 最佳实践
- ambari删除脚本
- sqoop 常用命令整理(一)
- hbase 学习(十三)集群间备份原理
- hbase 学习(十二)非mapreduce生成Hfile,然后导入hbase当中
- RavenDb学习(六)查询补充特性
- hbase源码系列(一)Balancer 负载均衡
- OpenCV在车道线查找中的使用
- hbase源码系列(十五)终结篇&Scan续集-->如何查询出来下一个KeyValue
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 猿思考系列5——一文明白java和微商那点儿事儿
- 猿思考系列8——缓存的套路也就这些
- 猿思考系列9——一文获取隐藏逻辑挖掘办法
- 猿蜕变系列1——春天的故事
- 猿蜕变系列2——一文搞懂spring的花式DI
- 猿蜕变系列3——SpringMVC之初体验
- 猿蜕变4——一文获取web框架正确学习套路
- 猿蜕变系列5——一文搞懂Controller的花式编写
- 猿蜕变系列6——一文掌握springMVC必会技巧
- ModuleNotFoundError: No module named ‘__main__.XX‘;
- 猿蜕变系列7——也说说springMVC上传姿势
- 猿蜕变系列8——一文搞懂Interceptor操纵姿势
- 猿蜕变9——一文搞定SpringMVC的RESTFul套路
- 猿蜕变10——一文学会ORM的正确打开姿势
- 猿蜕变11——一文掌握mybatis全局玩儿法