kingbaseES sql 优化技巧汇总
1、整体思路
针对业务系统的出现的慢sql 我们的优化步骤大概分为以下几步
1、识别高负载语句
2、收集性能相关的数据
3、确定性能问题产生的原因
4、实施优化手段
下面我们针对这几个步骤展开进行讲解
1、识别高负载语句
金仓数据库 kingbase ES针对满语句识别有以下几个工具
• sys_stat_statements
需要闯将sys_stat_statements 扩展 ,默认金仓数据库已经创建对应扩展
通过sys_stat_statements 查看数据库sql语句执行情况,发现有问题语句并进行优化
该视图可以查询内容包括
1、语句内容
2、语句执行次数
3、语句解析次数和时间
3、shared_buffer 使用情况是否用到了磁盘read 还是用到了 shared _buffer hit
4、temp_buffer ,work_me,maintance_men 命中情况 通过local字段排查
• kbbadger
kbbadger 是金仓提供的一款日志分析工具,通过该工具可以胜场html格式的sql执行情况分析报告。
生成要求和指令如下:
相关参数要求
log_min_duration_statement = 0 --需要reload
不要开启 log_statement 参数 --默认关闭
lc_messages='en_US.UTF-8' -必须是英文,否则无法解析
常见使用语句
kbbadger /var/log/kingbase.log
kbbadger /var/log/kingbase.log.2.gz /var/log/kingbase.log.1.gz /var/log/kingbase.log kbbadger
/var/log/kingbase/kingbase-2012-05-*
kbbadger --exclude-query="^(COPY|COMMIT)" /var/log/kingbase.log
kbbadger -b "2012-06-25 10:56:11" -e "2012-06-25 10:59:11" /var/log/kingbase.log
cat /var/log/kingbase.log | kbbadger -
kbbadger --prefix '%t [%p]: user=%u,db=%d,client=%h' /sys_log/kingbase-2012-08-21*
kbbadger --prefix '%m %u@%d %p %r %a : ' /sys_log/kingbase.log
# Log line prefix with syslog log output
kbbadger --prefix 'user=%u,db=%d,client=%h,appname=%a' /sys_log/kingbase-2012-08-21*
# Use my 8 CPUs to parse my 10GB file faster, much faster
kbbadger -j 8 /sys_log/kingbase-10.1-main.log
注意:CSV格式文件分析需要操作系统安装perl-text-CSV
安装语句
/usr/bin/perl5 -MCPAN -e'install Text::CSV_XS'
• KWR报告
KWR 报告需要借助于快照生成,由于快照时间间隔默认是1小时,所以实时性比较弱,但是在分析性能问题时建议首先收集一次KWR这样可以对数据库整体负载有一个全面的了解。
KWR的创建方法如下:
创建扩展
Create extension sys_kwr;
建议配置参数修改之后reload 即可,无需重启数据库
track_sql = on
track_instance = on -- KWR 1.3 新增参数
track_wait_timing = on -- 默认开启
track_counts = on --默认开启
track_io_timing = on
track_functions = 'all'
sys_stat_statements.track = 'top'
生成快照
CREATE EXTENSION sys_kwr;
SELECT * FROM perf.create_snapshot(); -- 获得快照 1
CREATE TABLE IF NOT EXISTS t1(id int); -- 创建一个示例表
SELECT count(*) FROM t1; -- 执行一些 SQL
SELECT * FROM perf.create_snapshot(); -- 获得快照 2
SELECT * FROM perf.kwr_report(1,2); -- 生成 TEXT 版本报告
SELECT * FROM perf.kwr_report(1,2, 'html'); -- 生成 HTML 版报告
• KSH报告
sys_ksh 以每秒采样的方式进行会话和数据收集,并将采集数据放入内存的 Ringbuf 队列中 对资源消耗大建议采用临时开启方式。
旧版本需要单独安装sys_ksh扩展, 新版本已经集成到sys_kwr 中
V8R6B24版本使用方法
Create extension sys_kwr;
sys_kwr.collect_ksh 设置 ksh=on 需要reload不需要重启
alter system set sys_kwr.collect_ksh =off
保存于内存 Ringbuf 的数据可以通过视图 perf.session_history 查看:
SELECT * FROM perf.session_history;
其中保存于数据库的历史数据可以通过视图 perf.ksh_history 查看:
SELECT * FROM perf.ksh_history;
生成的报告可以通过 perf.ksh_report 查看:
SELECT perf.ksh_report(start_ts, duration, slot_width, write_to_file);
参数说明:
• start_ts: 报告开始时间,默认:当前时间-15 分钟
• duration: 报告时长,默认到 15 分钟,最大不超过 60 •
slot_width: 报告最小区间,输入 0 时系统自动计算合适的宽度
• write_to_ffle: 是否输出到 sys_log 目录,默认否
KSH 输出报告的内容章节包括:
• Report & Instance Info: 报告和实例信息
• Top User Event: TOP 用户事件
• Top Background Event: TOP 后端事件
• Top SQL with Top Event: TOP 语句的 TOP 事件
• Complete List Of SQL Text: TOP 完整语句
• Top Session: TOP 会话
• Top Client Id: TOP 客户端
• Top SQL Command Type: TOP 语句命令类型
• Top Phase Of Execution: TOP 运行阶段
• Activity Over Time: 区间活动统计 实例运行效果如下:
2、收集性能相关的数据
其实在高负载sql识别时已经收集了一部分性能相关数据。在sql调优过程中还是以sql执行计划为主,但为了判断执行计划的准确性以及可能存在的其他性能问题还需要收集一些其他信息。
首先要了解相关表的结构和数据量和分布情况
select id,count(1) from t01 group by id; -- 查看某一个字段或者条件数据分布情况
select sys_relation_size('t01'); --查看表的大小
select count(1) from t01; --统计实际行数
然后收集执行计划
explain (analyze true,buffers true) select * from t01; -- select语句 可以使用analyze
explain (buffers true) updatae -- update语句不建议使用analyze
绑定变量方式收集执行计划
prepare a as select * from t01 where id=$1;
explain analyze execute a('1');"
sql执行情况分析
查看解析情况
select a.userid, b.usename, dbid, queryid, query, parses, max_parse_time, mean_parse_time from sys_stat_statements a ,sys_user b WHERE a.""userid"" = b.usesysid and b.usename='system';
查看 内存命中情况
select a.userid, b.usename, dbid, queryid, query, shared_blks_hit ""缓存读"", shared_blks_read ""IO读"" from sys_stat_statements a ,sys_user b WHERE a.""userid"" = b.usesysid;
查看等待事件 select a.usesysid, b.usename , wait_event_type,wait_event,state from sys_stat_activity a,sys_user b,sys_stat_statements c WHERE a.usesysid = b.usesysid AND a.query=c.""query"" and b.usename='system' AND c.""queryid"" ='';
查看是否有锁 通过查询sys_locks "
3、确定性能问题产生的原因&实施优化手段
通过以上收集的信息基本就可以判断出sql语句的性能问题并针对问题指定对应的优化措施
以下列举了一些常见的问以及对应解决方式
1、如果执行计划展示的预估row和实际执行rows数量差距比较大,表明统计信息不准确,建议收集统计信息
2、如果表的扫描方式是通过全表扫描即seq scan 方式执行的,需要分析where条件对应字段是的数据分布情况以及是否有索引。
3、判断join顺序的外部表和内部表,判断join顺序和方式是否合理,join方式是否合理。
4、sql语句有排序操作,可以通过执行计划的buffer选项判断是否用到是temp文件进行排序,如果用到了temp文件建议调整work_mem
5、部分慢语句确认执行计划已经最优,这时候可以尝试通过并行提速,但是建议使用hint方式开启并行,这样对全局影响最小。
6、通过分析该语句的内存命中情况发现IO读比较多,建议针对shared buffers 进行优化。
7、如果该语句长时间执行不返回结果建议查看等待时间和locks 视图排查是否有锁或等待事件。针对等待事件进行针对性调优。
8、在应用程序中尽可能使用预编译方式执行sql语句,降低因为解析带来的时间消耗。
9、表倾斜比较严重的情况进行查询可以进行反向条件方式优化,比如between 改成not between in 改成not in ,尽可能通过小的数据集完成join操作
表倾斜比较严重的情况进行查询可以进行反向条件方式优化,比如between 改成not between in 改成not in ,尽可能通过小的数据集完成join操作
10 、like 查询需要根据like 条件使用对应索引优化,金仓的btree索引针对‘aaa%'场景只有在colltion =C的情况下才走索引, 除此之外我们还可以使用
create index idx_t1 on t1(name text_pattern_ops);方式或者create table t1(id int, name text collate "C"); create index idx_t1 on t1(name); 进行like语句优化,
针对’%asb%‘ 情况我们需要创建对应的gin索引。 创建语句格式如下
create index idx_t2_trgm on t2 using gin(name gin_trgm_ops);
11、可以通过物化视图提前将大表的结果集减少,然后再利用物化视图进行sql查询。
注意事项
针对单条语句的sql 优化尽可能不要修改全局参数,或者进行库级别的调整,尽可能降低因为单条sql优化带来的全局风险
当然这篇博客整理的内容还是比较粗,有很多细节会在后续的博客中展开讲述
比如:
--cpu瓶颈判断方法
--IO是否饱和分析方法
--网络情况分析方法
--操作系统内存瓶颈分析方法
--如何判断执行计划不准确
--如何判断shared_buffer 不足
--如何判断排序用到了临时文件
--如何判断join顺序是否合适
--IO分析试图 sys_stdio_user_tables和 sys_stdio_user_indexes用法
-- sys_stat_activity 视图用法
-- sys_stat_statements 视图用法等