KingbaseES V8R6 documentation
2.3. 数据库资源分析
« 2.2. 操作系统资源分析 :: Contents :: 3. 第三部分 性能优化 »
2.3. 数据库资源分析¶
数据库运行时的状态对分析某些性能问题的分析至关重要,我们可用通过对系统状态统计信息、日志信息的分析,来监控整个数据库的运行状态,并能从其中发现一些性能相关的问题。
跟数据库性能相关的信息主要包括:
整体分析 | sys_kwr报告工具(基本覆盖所有优化点分析) sys_ksh工具 |
---|---|
CPU优化点分析 | 耗时语句统计: sys_stat_statements kbbadger |
会话/负载/等待事件分析 | sys_stat_activity视图(实时) sys_ksh报告工具(时间区间) |
锁优化点分析 | sys_locks视图 |
IO优化点分析分析 | sys_statio_user_tables视图 sys_statio_user indexes视图 |
应用特点分析 | sys_stat_user_tables视图 sys_stat_user_indexes视图 sys_stat_database视图 |
数据库内部提供了性能视图和日志系统来辅助做性能诊断,一般思路如下:
-
查看活跃连接和等待时间,看是否存在存在等待较多的等待事件。可能的等待事件包括:数据文件读/写、日志文件写、网络读、封锁等时间比较长的问题。
-
查看耗时语句,从高到底优化耗时语句的执行时间。
-
查看锁信息,看是否有锁无法获得的情况。
-
查看表和索引的命中率,看是否有命中率较低的情况。如果命中率较低,考虑提高shared_buffers。
-
查看是否有写临时文件的情况(设置log_temp_files参数)。如果有,是否是work_mem设置的太小了,导致排序内存放不下就写临时文件了,调整大一些(和查询的数据量有关)然后观察是否还写临时文件。
-
PB报文的比例是否正常,如果PB的比例相当,或者大量使用了Q报文,考虑将应用改写为规范的PBE协议,尽量复用执行计划。
2.3.1. CPU优化点分析¶
在数据库遭遇CPU瓶颈时,通过分析耗时SQL语句的执行计划可以有效的降低数据库的响应时间,提高吞吐量。
目前kingbase内部提供了2种工具来做耗时语句统计(kwr也集成了类似能力):
sys_stat_statement
sys_stat_statement是一个插件,通过共享内存来做数据记录,其特点如下:
-
对于同一类语句只做一条记录,有效节省时间和刷盘时间。
-
结果可以实时查看
-
无法查看语句中的参数信息、事务信息、执行时间等信息
kbbadger
kbbadger依赖于kingbase的日志系统来做记录,其特点如下:
-
同一类语句的信息都可以做记录,会带来IO压力。
-
需要将日志通过工具分析后才可以查看
-
还可以额外记录临时文件、checkpoint、绑定信息等
在得到耗时语句后,则需要对耗时语句做SQL性能分析,一般的分析包括:
-
统计信息是否够及时
-
是否有数据、索引膨胀的情况
-
是否缺少索引、分析、物化视图等访问结构
-
Join顺序、join算法等是否合理
-
是否有更高效的改写方式
有关SQL调优更详细的内容参见《KingbaseES V8 SQL调优指南》
2.3.1.1. 使用sys_stat_statement工具¶
sys_stat_statement是kingbaseES系统的一个扩展组件,它提供了所有执行语句的统计信息,可以帮助找出哪种类型的查询很慢以及多久调用一次查询。
使用这个模块的执行步骤:
-
在kingbase.conf里添加预加载项:
shared_preload_libraries = 'sys_stat_statements'
-
重启数据库服务器
-
在执行的数据库里创建扩展:
test=# create extension sys_stat_statements; CREATE EXTENSION
Note
从KingbaseES V8R6 版本开始,sys_stat_statements插件已经内置化,初始化数据库实例的时候,就会被自动加载。不过该功能默认关闭,需要设置:sys_stat_statements.track = 'top'才能正常使用。
名称 | 类型 | 描述 |
---|---|---|
userid | oid | 执行该语句的用户的 OID |
dbid | oid | 在其中执行该语句的数据库的 OID |
queryid | bigint | 内部哈希码,从语句的解析树计算得来 |
query | text | 语句的文本形式 |
parses | bigint | 该语句被解析的次数 |
total_parse_time | double precision | 在该语句中解析花费的总时间,以毫秒计 |
min_parse_time | double precision | 在该语句中解析花费的最小时间,以毫秒计 |
max_parse_time | double precision | 在该语句中解析花费的最大时间,以毫秒计 |
mean_parse_time | double precision | 在该语句中解析花费的平均时间,以毫秒计 |
stddev_parse_time | double precision | 在该语句中解析花费时间的总体标准偏差,以毫秒计 |
plans | bigint | 该语句执行Plan的次数 |
total_plan_time | double precision | 在该语句中执行Plan花费的总时间,以毫秒计 |
min_plan_time | double precision | 在该语句中执行Plan花费的最小时间,以毫秒计 |
max_plan_time | double precision | 在该语句中执行Plan花费的最大时间,以毫秒计 |
mean_plan_time | double precision | 在该语句中执行Plan花费的平均时间,以毫秒计 |
stddev_plan_time | double precision | 在该语句中执行Plan花费时间的总体标准偏差,以毫秒计 |
calls | bigint | 被执行的次数 |
total_exec_time | double precision | 在该语句中花费的总时间,以毫秒计 (该字段在 V8R5 里面为:total_time) |
min_exec_time | double precision | 在该语句中花费的最小时间,以毫秒计 (该字段在 V8R5 里面为:min_time) |
max_exec_time | double precision | 在该语句中花费的最大时间,以毫秒计 (该字段在 V8R5 里面为:max_time) |
mean_exec_time | double precision | 在该语句中花费的平均时间,以毫秒计 (该字段在 V8R5 里面为:mean_time) |
stddev_exec_time | double precision | 在该语句中花费时间的总体标准偏差,以毫秒计 (该字段在 V8R5 里面为:stddev_time) |
rows | bigint | 该语句检索或影响的行总数 |
shared_blks_hit | bigint | 该语句造成的共享块缓冲命中总数 |
shared_blks_read | bigint | 该语句读取的共享块的总数 |
shared_blks_dirtied | bigint | 该语句弄脏的共享块的总数 |
shared_blks_written | bigint | 该语句写入的共享块的总数 |
local_blks_hit | bigint | 该语句造成的本地块缓冲命中总数 |
local_blks_read | bigint | 该语句读取的本地块的总数 |
local_blks_dirtied | bigint | 该语句弄脏的本地块的总数 |
local_blks_written | bigint | 该语句写入的本地块的总数 |
temp_blks_read | bigint | 该语句读取的临时块的总数 |
temp_blks_written | bigint | 该语句写入的临时块的总数 |
blk_read_time | double precision | 该语句花在读取块上的总时间,以毫秒计 |
blk_write_time | double precision | 该语句花在写入块上的总时间,以毫秒计 |
出于安全原因,非超级用户不允许查看其他用户执行的SQL文本或queryid。但是,如果视图已安装在数据库中,则他们可以查看统计信息。
只要有计划的查询(即SELECT,INSERT,UPDATE和DELETE)根据内部哈希计算具有相同的查询结构,它们就会组合到单个sys_stat_statements条目中。通常,如果两个查询在语义上等效,则两个查询在此意义上相同,只是出现在查询中的文字常量的值除外。但是,将严格根据实用程序命令(即所有其他命令)的文本查询字符串进行比较。
当为了将查询与其他查询匹配而忽略了常量的值时,该常量将替换为?。在sys_stat_statements显示中,查询文本的其余部分是第一个查询的文本,该查询具有与sys_stat_statements条目关联的特定queryid哈希值。
在某些情况下,文本明显不同的查询可能会合并到一个sys_stat_statements条目中。通常,这仅会在语义上等效的查询中发生,但是散列冲突会导致不相关的查询合并到一个条目中的可能性很小。(但是,这对于属于不同用户或数据库的查询不会发生。)
该组件的主要配置参数:
-
sys_stat_statements.max(整数)
sys_stat_statements.max是模块跟踪的最大语句数(即sys_stat_statements视图中的最大行数)。如果观察到的语句不同,则将丢弃关于执行最少的语句的信息。默认值为5000。只能在服务器启动时设置此参数。
-
sys_stat_statements.track(枚举)
sys_stat_statements.track控制模块计算哪些语句。指定top以跟踪顶级语句(由客户端直接发出的语句),全部也可以跟踪嵌套语句(例如在函数内调用的语句),或者不指定以禁用语句统计信息收集。默认值为top。仅超级用户可以更改此设置。
注意:该参数在 V8R5 里默认值为’top’,如果需要使用sys_stat_statements功能,需要将其配置为’top’。
-
sys_stat_statements.track_utility(boolean)
sys_stat_statements.track_utility控制模块是否跟踪实用程序命令。实用程序命令是除SELECT,INSERT,UPDATE和DELETE之外的所有命令。默认值为on。仅超级用户可以更改此设置。
-
sys_stat_statements.save(boolean)
sys_stat_statements.save指定是否在服务器关闭时保存语句统计信息。如果关闭,则统计信息不会在关闭时保存,也不会在服务器启动时重新加载。默认值为on。只能在kingbase.conf文件或服务器命令行中设置此参数。
该模块需要与sys_stat_statements.max成比例的附加共享内存。请注意,即使sys_stat_statements.track设置为none,只要加载模块,就会消耗此内存。
这些参数必须在kingbase.conf中设置。典型用法可能是:
#kingbaseconf shared_preload_libraries =' sys_stat_statements'sys_stat_statements.max = 10000 sys_stat_statements.track =all
2.3.1.2. 使用kbbadger工具¶
Kbbadger可以分析大型的日志文件。当日志文件足够长时,kbbadger可以自动检测日志文件的格式(syslog,stderr,csvlog或jsonlog)。
由kbbadger生成的所有图表都是可缩放的并且可单独下载为PNG文件。另外,在生成的报告中SQL查询将突出显示。
Kbbadger生成的报告中包含的关于SQL查询的信息有:
-
总体统计
-
占用时间最多的查询
-
最常见的查询
-
最常见的错误
-
查询时间直方图
-
会话时间直方图
-
参与顶级查询的用户
-
涉及顶级查询的应用程序
-
生成最多取消的查询
-
大多数查询已取消
-
最耗时的准备/绑定查询
报告也会提供每小时的统计图表,其内容包括:
-
SQL查询统计信息
-
临时文件统计
-
检查点统计
-
自动vacuum和自动分析统计
-
已取消查询
-
错误事件(死机、致命、错误和警告)
-
错误的类分布
在kbbadger的使用过程中,可以使用命令行选项来启用并行处理模式从而加快日志解析速度,使用-j命令行选项来指定解析使用的CPU核心数,使用-J命令行选项来并行解析的文件数,两个选项可以同时使用。另外,可以使用-A命令行选项来调整直方图的粒度。默认情况下,它们将报告每小时发生的每个主要查询/错误的平均值。
使用方法
-
配置kingbase.conf
在开始之前,必须在kingbase.conf中启用并设置一些配置指令。
您必须首先启用SQL查询日志记录才能进行解析:
log_min_duration_statement = 0
在这里,每条语句都会被记录,在繁忙的服务器上,您可能需要增加此值以仅记录持续时间较长的查询。请注意,不要启用log_statement,因为kbBadger不会解析它的日志格式并且如果您将log_statement设置为'all',则不会通过log_min_duration_statement指令记录任何内容。如果要保证系统性能,也可以使用log_duration来仅提供有关持续时间和查询数量的报告。有关更多信息,请参见下一章。
kbBadger支持任何设置到kingbase.conf文件的log_line_prefix中的自定义格式,只要它指定时间转义序列(%t,%m或%n)和与进程相关的转义序列(%p或%c)。
例如:
使用“ stderr”日志格式,log_line_prefix必须至少为: log_line_prefix = '%t [%p]: ' 日志行前缀可以添加用户,数据库名称,应用程序名称和客户端IP地址,如下所示: log_line_prefix = '%t [%p]: user=%u,db=%d,app=%a,client=%h ' 或用于syslog日志文件格式: log_line_prefix = 'user=%u,db=%d,app=%a,client=%h ' stderr输出的日志行前缀也可以是: log_line_prefix = '%t [%p]: db=%d,user=%u,app=%a,client=%h ' 或用于syslog输出: log_line_prefix = 'db=%d,user=%u,app=%a,client=%h ' 您也可以在kingbase.conf中启用其他参数,以从日志文件中获取更多信息: log_checkpoints = on log_connections = on log_disconnections = on log_lock_waits = on log_temp_files = 0 log_autovacuum_min_duration = 0 log_error_verbosity = default
Note
数据库日志中的内容必须为英文,否则kbbadger可能无法解析日志中的内容:
lc_messages='en_US.UTF-8'
-
使用kbBadger生成统计信息
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
详细请参见 –help
-
举例说明
$ ./kbbadger ./ sys_log/kingbase-2019-10-26_1544* -f stderr -J 12 -j 32 [========================>] Parsed 283210387 bytes of 283210387 (100.00%), queries: 327810, events: 51 LOG: Ok, generating html report...
生成的统计信息效果图如下:
2.3.2. 等待事件分析¶
为了了解数据库当前的运行时状态,管理员可以查看系统视图sys_stat_activity来进行查看。该视图能够知道数据库目前正在发生写什么:比如有多少个连接,客户端的情况,每个连接的状态,每个连接上的等待事件等。
Note
当前执行的查询语句和等待事件状态需要在开启track_activities参数的情况下才可以查看。开启该参数会带来一定的性能损耗。
2.3.2.1. 活跃连接¶
字段名 | 类型 | 说明 |
---|---|---|
datid | oid | 数据库OID |
datname | name | 数据库名称 |
pid | integer | 服务于这个连接的进程ID |
usesysid | oid | 用户ID |
usename | name | 用户名 |
application_name | text | 应用名称 |
client_addr | inet | 客户端地址 |
client_hostname | text | 客户端主机名 |
client_port | integer | 客户端端口号 |
backend_start | timestamp with time zone | 该连接的启动时间 |
xact_start | timestamp with time zone | 当前事务开始时间 |
query_start | timestamp with time zone | 当前查询开始时间 |
state_change | timestamp with time zone | 当前状态改变时间 |
wait_event_type | text | 当前等待事件的类型 |
wait_event | text | 当前等待事件 |
state | text | 当前的状态 |
backend_xid | xid | 这个后端的顶层事务标识符 |
backend_xmin | xid | 这个进程的当前事务被启动的时间 |
query | text | 当前查询语句 |
其中,state为当前连接的状态,其可能的值主要有:
-
active:后端正在执行一个查询。
-
idle:后端正在等待一个新的客户端命令。
-
idle in transaction:后端在一个事务中,但是当前没有正在执行一个查询。
-
idle in transaction (aborted):这个状态与idle in transaction相似,不过在该事务中的一个语句导致了一个错误。
-
fastpath function call:后端正在执行一个 fast-path 函数。
-
disabled:如果在这个后端中 track_activities 被禁用,则报告这个状态。
Note
如果一个查询或者事务执行的时间过长而一直没有结束,很有可能会拖累整个系统的性能表现,需要具体分析问题的原因并采取合适的办法。
2.3.2.2. 等待事件¶
等待事件是数据库内部记录的一种统计信息,该信息出现表明数据库的服务进程必须在等待事件完成后才能继续处理。等待事件揭示了可能影响性能的各种问题症状,比如缓冲区中争用、锁争用等。
sys_stat_activity里记录的等待事件是瞬时信息,没有对等待事件的时间进行累计,所以量化等待事件上存在一些问题。用户可以考虑多次人工采样来收集等待事件信息,如果在等待的连接较多,则需要等待事件对系统性能造成了较大影响,需要做具体分析。
Note
当前执行的查询语句和等待事件状态需要在开启track_activities参数的情况下才可以查看。开启该参数会带来一定的性能损耗。
sys_stat_activity视图中,wait_event_type和wait_event字段记录了等待时间相关的内容。当一个会话处于等待状态时,wait_event与wait_event_type两列非空,表示会话正在等待的事件和等待事件类型。
wait_event_type的可能值有:
-
LWLockNamed:后端正在等待一个特定命名的轻量级锁。每一个这样的锁保护共享内存中的一个特定数据结构。wait_event将包含该轻量级锁的名称。
-
LWLockTranche:后端正在等待一组相关轻量级锁中的一个。该组中的所有锁都执行一种相似的功能。wait_event将标识这个组中锁的大体目的。
-
Lock:后端正在等待一个重量级锁。重量级锁,也称为锁管理器锁或者简单锁,主要保护 SQL 可见的对象,例如表。不过,它们也被用于确保特定内部操作的互斥,例如关系扩展。wait_event将标识等待的锁的类型。
-
BufferPin:服务器进程正在等待访问一个数据缓冲区,而此时没有其他进程正在检查该缓冲区。如果另一个进程持有一个最终从要访问的缓冲区中读取数据的打开的游标,缓冲区 pin 等待可能会被拖延。
wait_event为等待事件名称,包括以下:
等待事件类型 | 等待事件名称 | 描述 |
---|---|---|
LWLockNamed | ShmemIndexLock | 正等待在共享内存中查找或者分配空间。 |
OidGenLock | 正等待分配或者赋予一个 OID。 | |
XidGenLock | 正等待分配或者赋予一个事务ID。 | |
ProcArrayLock | 正等待在事务结尾得到一个快照或者清除事务ID。 | |
SInvalReadLock | 正等待从共享无效消息队列中检索或者移除消息。 | |
SInvalWriteLock | 正等待在共享无效消息队列中增加一个消息。 | |
WALBufMappingLock | 正等待在 WAL 缓冲区中替换一个页面。 | |
WALWriteLock | 正等待 WAL 缓冲区被写入到磁盘。 | |
ControlFileLock | 正等待读取或者更新控制文件或创建一个新的WAL文件。 | |
CheckpointLock | 正等待执行检查点。 | |
CLogControlLock | 正等待读取或者更新事务状态。 | |
SubtransControlLock | 正等待读取或者更新子事务信息。 | |
MultiXactGenLock | 正等待读取或者更新共享多事务状态。 | |
MultiXactOffsetControlLock | 正等待读取或者更新多事务偏移映射。 | |
MultiXactMemberControlLock | 正等待读取或者更新多事务成员映射。 | |
RelCacheInitLock | 正等待读取或者写入关系缓冲区初始化文件。 | |
CheckpointerCommLock | 正等待管理fsync请求。 | |
TwoPhaseStateLock | 正等待读取或者更新预备事务的状态。 | |
TablespaceCreateLock | 正等待创建或者删除表空间。 | |
BtreeVacuumLock | 正等待读取或者更新一个 B-树索引的vacuum相关的信息。 | |
AddinShmemInitLock | 正等待管理共享内存中的空间分配。 | |
AutovacuumLock | 自动清理工作者或者启动器正等待更新或者读取自动清理工作者的当前状态。 | |
AutovacuumScheduleLock | 正等待确认选中进行清理的表仍需要清理。 | |
SyncScanLock | 正等待为同步扫描得到一个表上扫描的开始位置。 | |
RelationMappingLock | 正等待更新用来存储目录到文件节点映射的关系映射文件。 | |
AsyncCtlLock | 正等待读取或者更新共享通知状态。 | |
AsyncQueueLock | 正等待读取或者更新通知消息。 | |
SerializableXactHashLock | 正等待检索或者存储有关可序列化事务的信息。 | |
SerializableFinishedListLock | 正等待访问已结束可序列化事务的列表。 | |
SerializablePredicateLockListLock | 正等待在由可序列化事务持有的所列表上执行一个操作。 | |
OldSerXidLock | 正等待读取或者记录冲突的可序列化事务。 | |
SyncRepLock | 正等待读取或者更新有关同步复制的信息。 | |
BackgroundWorkerLock | 正等待读取或者更新后台工作者状态。 | |
DynamicSharedMemoryControlLock | 正等待读取或者更新动态共享内存状态。 | |
AutoFileLock | 正等待更新kingbase.auto.conf文件。 | |
ReplicationSlotAllocationLock | 正等待分配或者释放一个复制槽。 | |
ReplicationSlotControlLock | 正等待读取或者更新复制槽状态。 | |
CommitTsControlLock | 正等待读取或者更新事务提交时间戳。 | |
CommitTsLock | 正等待读取或者更新事务时间戳的最新设置值。 | |
ReplicationOriginLock | 正等待设置、删除或者使用复制源头。 | |
MultiXactTruncationLock | 正等待读取或者阶段多事务信息。 | |
OldSnapshotTimeMapLock | 正等待读取或者更新旧的快照控制信息。 | |
LWLock Tranche | clog | 正等待一个 clog(事务状态)缓冲区上的 I/O。 |
commit_timestamp | 正等待提交时间戳缓冲区上的 I/O。 | |
subtrans | 正等待子事务缓冲区上的 I/O。 | |
multixact_offset | 正等待多事务偏移缓冲区上的 I/O。 | |
multixact_member | 正等待多事务成员缓冲区上的 I/O。 | |
async | 正等待 async(通知)缓冲区上的 I/O。 | |
oldserxid | 正等待oldserxid缓冲区上的 I/O。 | |
wal_insert | 正等待把 WAL 插入到一个内存缓冲区。 | |
buffer_content | 正等待读取或者写入内存中的一个数据页。 | |
buffer_io | 正等待一个数据页面上的 I/O。 | |
replication_origin | 正等待读取或者更新复制进度。 | |
replication_slot_io | 正等待一个复制槽上的 I/O。 | |
proc | 正等待读取或者更新 fast-path 锁信息。 | |
buffer_mapping | 正等待把一个数据块与缓冲池中的一个缓冲区关联。 | |
lock_manager | 正等待增加或者检查用于后端的锁,或者正等待加入或者退出一个锁定组(并行查询使用)。 | |
predicate_lock_manager | 正等待增加或者检查谓词锁信息。 | |
Lock | relation | 正等待获得一个关系上的锁。 |
extend | 正等待扩展一个关系。 | |
page | 正等待获得一个关系上的页面的锁。 | |
tuple | 正等待获得一个元组上的锁。 | |
transactionid | 正等待一个事务结束。 | |
virtualxid | 正等待获得一个虚拟xid锁。 | |
speculative token | 正等待获取一个 speculative insertion lock。 | |
object | 正等待获得一个非关系数据库对象上的锁。 | |
userlock | 正等待获得一个用户锁。 | |
advisory | 正等待获得一个咨询用户锁。 | |
BufferPin | BufferPin | 正等待在一个缓冲区上加 pin |
关于等待事件,可以使用下面例子中的SQL语句对其进行查询。
benchmarksql=# select wait_event_type,wait_event,state,count(*) from sys_stat_activity group by wait_event_type,wait_event,state; wait_event_type| wait_event | state |count ---------------+--------------------+-------------------+----- LWLock | buffer_mapping |idle in transaction| 1 Activity | BgWriterMain | | 1 | | active | 92 Activity |LogicalLauncherMain | | 1 Activity | CheckpointerMain | | 1 Client | ClientRead | active | 16 LWLock | buffer_mapping | active | 74 Client | ClientRead | idle | 2 | |idle in transaction| 22 | | disabled | 1 LWLock | buffer_mapping | idle | 1 LWLock | ProcArrayLock | active | 1 | | idle | 1 Lock | transactionid | active | 3 Activity | WalWriterMain | | 1 IPC |ProcArrayGroupUpdate|idle in transaction| 16 IPC |ProcArrayGroupUpdate|active | 155 Client | ClientRead |idle in transaction| 17 (18 rows)
如果某个活跃连接经常出现长时间的等待事件,则需要对其进行进一步的分析。
例如:
我们在跑高并发的tpcc时,可能看到如下等待事件。
采样几次以后,发现等待事件ProcArrayGroupUpdate一直过高。
ProcArrayGroupUpdate 等待事件,指事务结束后,将当前xid从ProcArray移除的事件。
此时我们就可以将lw_snap参数设置为off来减缓锁压力。
2.3.3. I/O优化点分析¶
2.3.3.1. 共享内存命中率分析¶
系统表sys_stdio_user_tables和sys_stdio_user_indexes从I/O的角度记录用户表和用户索引的信息。如果命中率过低,则可以考虑加大shared_buffers。
1、sys_stdio_user_tables
视图内容:当前数据库中用户表上的 I/O 统计信息。
列名 | 类型 | 描述 |
---|---|---|
relid | oid | 该表的oid |
schemaname | name | 表空间名 |
relname | name | 表名 |
heap_blks_read | bigint | 从该表读取的磁盘块数 |
heap_blks_hit | bigint | 该表中的缓冲区命中数 |
idx_blks_read | bigint | 从该表上所有索引读取的磁盘块数 |
idx_blks_hit | bigint | 该表上所有索引中的缓冲区命中数 |
toast_blks_read | bigint | 从此表的TOAST表中读取的磁盘块数(如果有) |
toast_blks_hit | bigint | 该表的TOAST表中的缓冲区命中数(如果有) |
tidx_blks_read | bigint | 从此表的TOAST表索引中读取的磁盘块数(如果有) |
tidx_blks_hit | bigint | 该表的TOAST表索引中的缓冲区命中数(如果有) |
2、sys_stdio_user_indexes
视图内容:当前数据库中用户表上的索引上的 I/O 统计信息。
列名 | 类型 | 描述 |
---|---|---|
relid | oid | 拥有该索引表的oid |
indexrelid | oid | 该索引的oid |
schemaname | name | 表空间名 |
relname | name | 拥有该索引表的名字 |
indexrelname | name | 索引名 |
idx_blks_read | bigint | 从该索引读取的磁盘块数 |
idx_blks_hit | bigint | 该索引中的缓冲区命中数 |
2.3.3.2. 私有内存使用分析¶
当一些Query的操作,使用的内存量大于指定阈值时,就会触发使用临时文件。包括排序,DSTINCT,MERGE JOIN,HASH JOIN,哈希聚合,分组聚合,递归查询等操作。
要统计数据库运行中是否触发了临时文件,可以通过修改参数log_temp_files(整数)记录tempfile统计到日志中。
log_temp_files:
控制临时文件名和大小的日志记录。可以为排序,哈希和临时查询结果创建临时文件。删除每个临时文件后,都会为其创建一个日志条目。零值记录所有临时文件信息,而正值仅记录大小大于或等于指定千字节数的文件。默认设置为-1,它将禁用此类日志记录。仅超级用户可以更改此设置。
例如:
执行查询进行order by
日志中输出临时文件信息
2.3.4. 锁优化点分析¶
视图sys_locks提供对有关数据库服务器内活动进程所持有的锁的信息的访问。
Name | Type | Description |
---|---|---|
locktype | text | 可锁对象的类型: relati on, extend, page, tuple,transactio nid, virtualxid, object, userlock, or advisory |
database | oid | 锁目标存在的数据库的OID,如果目标是一个共享对象则为0,如果目标是一个事务ID则为空 |
relation | oid | 作为锁目标的关系的OID,如果目标不是一个关系或者只是关系的一部分则此列为空 |
page | integer | 作为锁目标的页在关系中的页号,如果目标不是一个关系页或元组则此列为空 |
tuple | smallint | 作为锁目标的元组在页中的元组号,如果目标不是一个元组则此列为空 |
virtualxid | text | 作为锁目标的事务虚拟ID,如果目标不是一个虚拟事务ID则此列为空 |
transactionid | xid | 作为锁目标的事务ID,如果目标不是一个事务ID则此列为空ID |
classid | oid | 包含锁目标的系统目录的OID,如果目标不是一个普通数据库对象则此列为空 |
objid | oid | 锁目标在它的系统目录中的OID,如果目标不是一个普通数据库对象则为空 |
objsubid | smallint | 锁的目标列号(classid和 objid指表本身),如果目标是某种其他普通数据库对象则此列为0,如果目标不是一个普通数据库对象则此列为空 |
virtualtransaction | text | 保持这个锁或者正在等待这个锁的事务的虚拟ID |
pid | integer | 保持这个锁或者正在等待这个锁的服务器进程的PID,如果此锁被一个预备事务所持有则此列为空 |
mode | text | 此进程已持有或者希望持有的锁模式 |
granted | boolean | 如果锁已授予则为真,如果锁被等待则为假 |
fastpath | boolean | 如果锁通过快速路径获得则为真,通过主锁表获得则为假 |
sys_locks每个活动的可锁定对象,请求的锁定模式和相关进程包含一行。因此,如果多个进程正在持有或等待对其进行锁定,则同一可锁定对象可能会出现多次。但是,当前没有锁的对象将根本不会出现。
有几种不同类型的可锁定对象:整个关系(例如表),单个关系页面,单个元组关系,事务ID(虚拟ID和永久ID)以及通用数据库对象(由OID类和OID对象标识,以与sys_description或sys_depend相同的方式)。同样,扩展关系的权利也表示为单独的可锁定对象。另外,可以对具有用户定义含义的数字进行“建议”锁定。
2.3.5. 自动负载信息库SYS_KWR¶
SYS_KWR是Kingbase自动负载信息库(Kingbase Auto Workload Repertories)的简称,它通过周期性自动记录性能统计相关的快照,分析出KES的操作系统运行环境、数据库时间组成、等待事件和TOP SQL等性能指标,为数据库性能调优提供指导。
2.3.5.1. SYS_KWR插件¶
KWR以插件的形式存在于KES产品中,目前V8R6C4中的最新版本是1.1。
如果开启了KWR自动快照功能,会自动在test库上创建该插件。否则可以通过SQL语句在目标库上创建:
KWR依赖sys_stat_statements插件(1.9版本),该插件是内置插件,会在所有库上自动被创建。
以下是创建KWR插件后查到的信息:
2.3.5.2. 基本原理¶
KWR的基本原理:数据库实例运行过程中不断产生一些统计数据,比如对某个表的访问次数,数据页的内存命中次数,某个等待事件发生的次数和总时间,SQL语句的解析时间等,这些统计数据被一个叫做KWR collector的后台性能监控进程周期性地(默认每小时)自动采集,存储到KWR快照库里面,这些快照默认保存8天,到期后那些旧的快照被自动删除。
当出现性能问题的时候,可以通过指定时间段来查询相关快照列表,生成KWR报告,定位性能问题的根本原因。
其他性能组件比如KDDM,基于KWR快照提供自动建议,该组件目前处于内侧阶段,尚不对外提供。
2.3.5.3. 快速生成报告¶
配置文件kingbase.conf,开启统计开关,其中shared_preload_libraries根据实际需要设置即可,需要包含下面的3个插件项:
重启服务器。通过KSQL连接,创建KWR插件,创建快照,执行SQL后再次创建快照,就可以生成KWR报告了:
kwr_report(1,2) 生成TEXT格式报告。kwr_report(1, 2, 'html') 生成HTML 格式的报告。生成的KWR报告会自动保存到DATA目录下的sys_log子目录下:
推荐使用HTML格式,因为它更便于阅读:
2.3.5.4. KWR价值¶
KWR通过自动采集操作系统和数据库实例的性能数据,将其存储为KWR快照,并依此来生成KWR报告为DBA性能调优提供参考,其价值包括:
-
自动采集操作系统统计信息,不需要额外的性能监控工具
-
感知数据库运行环境,排查数据库实例外部原因造成的性能问题
-
通过统一的DB Time模型,度量数据库关键活动耗时
-
通过query ID将SQL执行时间、等待时间和资源消耗关联起来,进行语句级分析
-
从多个维度(时间、IO、锁、实例、库对象等)分析数据库实例的性能问题
-
自动生成快照,便于回溯之前发生的性能问题
-
为KDDM等自动诊断和建议提供基础数据
2.3.5.5. 使用SYS_KWR¶
2.3.5.5.1. 配置GUC参数¶
KWR依赖内核stats模块采集性能统计数据,建议开启以下GUC参数,否则KWR报告里会缺失部分内容:
track_sql = on track_counts = on track_wait_timing = on track_io_timing = on track_functions = 'all'
几个参数的说明如下:
-
track_sql:统计SQL时间、SQL等待事件、SQL IO,默认为off,必须开启
-
track_count:统计数据库活动,默认为on
-
track_wait_timing:统计累积式等待事件的时间,默认为off,建议开启
-
track_io_timing:统计IO耗时,默认为off,建议开启
-
track_functions:统计用户自定义函数使用情况,默认为'none',建议 'all'
KWR依赖内核sys_stat_statements插件采集TOP SQL统计数据,必须开启以下GUC参数,否则无法创建KWR快照:
sys_stat_statements.track = 'top'
KWR相关参数:
-
sys_kwr.enable:开启自动快照功能,默认为false
-
sys_kwr.topn:kwr报告显示topn条件记录,默认20条
-
sys_kwr.history_days:kwr快照数据保留天数,默认8天
-
sys_kwr.interval:kwr自动采集快照的间隔,默认60分钟
Note
1、 要打开自动快照功能,需要将sys_kwr.enable设置为true
2、 任何情况下都可以执行:select * from perf.create_snapshot(); 来手工创建快照
3、 自动快照会在test库上创建 sys_kwr插件
4、 shared_preload_libraries里至少包含:liboracle_parser, sys_kwr, sys_stat_statements
2.3.5.5.2. 快照查询¶
快照的查询通过 perf.kwr_snapshots 即可:
2.3.5.5.3. 自动快照¶
只需要将sys_kwr.enable设置为true(需要重启服务器),就开启了自动快照功能。
后台进程 kwr collector每分钟检查最后一次快照的时间,跟当前的时间间隔是否大于sys_kwr.interval。如果大于则立刻创建新的快照,并更新最后快照时间。
如果本次自动快照没有创建成功,则在下一个检查周期(一分钟后)继续尝试创建快照。
2.3.5.5.4. 手动快照¶
配置好相关的GUC参数后,执行perf.create_snapshot() 创建手工快照,返回新的快照号,同时也在perf.kwr_snapshots里添加一条记录:
2.3.5.5.5. 快照管理¶
一般情况下,不需要手工管理已经生成的快照,KWR会在每次创建新的快照时,自动删除已经超过sys_kwr.history_days 天的快照数据,避免快照数据过多导致性能问题。
可以通过perf.drop_snapshots() 删除部分不再需要的快照:
或者通过perf.reset_snapshots() 清理全部快照:
2.3.5.5.6. 生成KWR报告¶
生成TEXT格式的KWR报告:
生成HTML格式的KWR报告:
生成的报告自动保存到data目录的sys_log子目录下:
如果想将生成KWR报告保存到指定的磁盘目录下,用kwr_report_to_file()函数,第4个参数指定文件全路径:
2.3.5.5.7. 常见问题¶
1、 KWR目前无法在高可用备节点上创建快照:
也无法在备节点上生成KWR报告:
2、 如果别的会话正在当前库上创建快照(还没有完成),为了防止快照管理数据混乱,此时不允许创建快照,必须等正在创建的快照完成:
3、 KWR依赖sys_stat_statements.track = 'top',否则不允许创建快照:
4、 KWR依赖track_sql = on,否则不允许创建快照:
5、 如果指定的快照不存在,生成报告时会报错:
6、 KWR目前不能在Windows平台采集操作系统数据,报告中相关内容会为空。
7、 创建快照时提示字符串拼接语法错误:
解决:添加liboracle_parser,因为KWR SQL里使用了字符串拼接语法 shared_preload_libraries = 'liboracle_parser, sys_kwr, sys_stat_statements'
2.3.5.6. 查看SYS_KWR报告¶
2.3.5.6.1. 报告结构¶
KWR报告主要由三部分组成:
1、报告头:
这部分主要是列出数据库实例的版本、运行环境和快照信息。
2、报告摘要:
这是整个报告的精华所在,大部分的性能问题都能够从这部分报告里看到。看这部分内容的时候,如果有必要,还可以结合后面的详细报告具体分析问题。
这部分最重要的几个报告是:负载统计表(Load Profile)、实例效率百分比(Instance Efficiency Percentages)、前台等待事件(Top 10 Foreground Wait Events)、主机环境统计(Host CPU、Host IO、Host Memory、Host Network)。
3、报告主体:
报告主体提供了更加全面的性能指标,主要包括:DB Time模型、等待事件、SQL报文统计、TOP SQL统计、后台写统计、数据库对象统计和配置参数。
2.3.5.6.2. 查看报告头¶
报告头部分主要由三部分组成:
1、 数据库实例和版本信息
字段说明:
-
Start Up:数据库实例启动时间
-
Release:数据库Release版本号
2、 主机环境
这部分主要说明数据库实例的运行环境,包括OS信息和一些硬件信息。
字段说明:
-
Host Name:主机名称
-
Platform:操作系统名称
-
CPUs:逻辑CPU个数
-
Cores:CPU核心数
-
Sockets:CPU socket数(物理槽位)
-
Memory:主机总共的内存大小
3、 快照信息
字段说明:
-
Snap ID:快照ID
-
Snap Time:快照时间
-
Sessions:快照时刻session数量
统计项说明:
-
Begin Snap:开始快照统计
-
End Snap:结束快照统计
-
Elapsed:开始和结束快照经历的时间,单位为分钟
-
DB Time:开始和结束快照期间花费在数据库上的时间总和
2.3.5.6.3. 分析DB Time¶
DB Time,就是数据库时间,它用来衡量数据库的繁忙程度,DB Time越高,说明数据库业务越繁忙。
如报告所示,在9.96分钟的快照时间内,有601.18分钟在执行数据库任务,说明数据库业务已经比较繁忙了。
从Load Profile里看平均每秒的DB Time是60.42,说明总共112个CPU里,有60.42个CPU工作在当前数据库实例上。满负荷的情况下,每秒的DB Time会接近CPU个数。当然服务器上的其它进程比如TPCC的JAVA进程也会占用10到20个CPU左右。
可以从详细报告的Time Model Statistics里看 DB time的各组成部分:
2.3.5.6.4. 查看报告摘要¶
报告摘要主要从总体的角度描述数据库性能,包括数据库实例的整体负载情况,实例效率百分比,排名靠前的等待事件,主机环境、IO和共享内存等性能指标。
一般来说,分析完报告摘要部分就能大体了解性能情况,甚至知道可能性能问题所在,直接就能调优了。也可以进一步结合详细报告来验证和分析问题。
以下是报告摘要的内容列表:
2.3.5.6.5. 负载性能表¶
负载性能表从总体上描述数据库负载情况,其中比较重要的性能指标参数有:DB Time, DB CPU, Foreground Wait Time, WAL Size, Blocks Read/Write Size等。
字段说明:
-
Metric:统计项
-
Total Values:统计项的绝对值(快照期间发生的统计)
-
Per Second:每秒平均发生的值(Total Values / Elapsed time)
-
Per Transaction:每个事务平均发生的值(Total Values / Transactions)
-
Per Exec:每个SQL执行平均发生的值(Total Values / Execute Calls)
统计项分5个部分说明:
1、DB Time统计
-
DB Time(s):DB Time是Backend进程非空闲等待的时间之和,单位为秒
-
DB CPU(s):DB Time – Backend进程非空闲等待时间,单位为秒
-
Foreground Wait Time(s):Backend进程非空闲等待时间,单位为秒
2、IO 统计
-
WAL Size(MB):写入的WAL日志大小,单位为MB
-
Blocks Hit:共享、本地和临时blocks命中块数
-
Blocks Read:共享、本地和临时blocks物理读块数
-
Blocks Dirty:共享、本地和临时blocks在内存中发生了更改的块数
-
Blocks Write:共享、本地和临时blocks物理写块数
-
Blocks Read Size(MB):共享、本地和临时blocks物理读的大小,单位为MB
-
Blocks Write Size(MB):共享、本地和临时blocks物理读的大小,单位为MB
IO方面需要重点关注的指标有WAL Size - WAL日志IO大小,和Blocks Read/Write Size - 数据页读和写的大小,这是物理读写的大小。
3、解析和执行次数统计
-
Parse Calls:SQL解析执行的次数
-
Plan Calls:SQL Plan的次数
-
Execute Calls:SQL Execute的次数
解析方面需要关注解析次数和执行次数的比例情况,如果解析过多,则必然Parser Calls跟Execute Calls更接近,说明解析效率不高。Plan 也是。
4、元组统计
-
Tuples Return:返回元组的数量
-
Tuples Fetch:Fetch元组的数量
-
Tuples Insert:Insert元组的数量
-
Tuples Update:Update元组的数量
-
Tuples Delete:Delete元组的数量
元组方面大概看一下增删改查的比例就好,了解一下大概的业务类型。
5、事务统计
-
Commits:完成事务提交的数量
-
Rollbacks:回滚事务的数量
-
Transactions:事务总数(Commits + Rollbacks)
事务方面看看回滚的事务是不是比例高,如果比例高是不是需要分析一下业务逻辑。
2.3.5.6.6. 实例效率百分比¶
实例效率百分比展示数据库实例跟重复利用Blocks、解析、计划的效率百分比情况,这些值在优化的比较好的测试环境里几乎都接近100%,比如BenchmarkSQL测试。
如果低于90%,说明数据页缓存不够(Buffer Hit),需要加大Shared_buffers,让更多的数据页通过缓存级能命中,较少IO;或者说明解析和计划效率不高,发生了大量的硬解析的,需要从业务端把Simple Query(select * from t1 where id = 5)通过扩展SQL协议来执行,即绑定变量的方式来执行。
字段说明:
-
Efficiency:效率统计项
-
Percentages:效率百分比,越高越好
统计项说明:
-
Buffer Hit:Shared和Local内存块的命中率,计算公式为:Blocks Hit * 100.0 / (Blocks Hit + Read)
-
Execute To Parse:Parse次数占Execute次数的百分比,这个值高说明SQL重用率高,计算公式为:Execute to Parse = 100 * (1 - Parses / Executes)
-
Execute To Plan:Plan次数占Execute次数的百分比,这个值高说明SQL重用率高,计算公式为:Execute to Parse = 100 * (1 - Parses / Executes)
2.3.5.6.7. Top 10前台等待事件¶
该报表显示花费等待时间最多的10个前台等待事件,从该报告可以看出数据库实例在主要在等待什么。当出现性能问题的时候,需要首先分析占比过高的前台等待事件,尤其那种大约DB Time 5% 以上的等待事件,往往是发现性能问题的关键线索。
这个报告里可以看到 DataFileRead 等待事件发生了2497次,DB Time比例超过30%,说明发生了严重的IO等待,存在大量的物理读。可以通过加数据页预先加载到内存的方式来较少物理读。
然后是WAL日志的3个等待事件也比较高,可以通过扩大WAL日志缓冲区、修改WAL刷盘的方式来减少WAL日志的写压力。
另外,平均等待时间也值得关注,比如报告里的 transactionid的平均等待时间是 9.23 毫秒,说明分配事务ID的锁冲突太厉害了。
在详细报告里可以进一步看到前台等待事件的信息。
字段说明:
-
Wait Event:等待事件名称
-
Wait Calls:等待次数
-
Total Time(s):等待事件,单位为秒
-
Avg Time(ms):平均一次等待的时间,单位为毫秒
-
% DB Time:等待事件占DB time的百分比,超过5% 的都需要重点分析
-
Wait Class:等待事件所属分类
2.3.5.6.8. Top 10前台等待事件分类¶
该报表显示花费等待时间最多的10个前台等待事件分类。
从该报告可以方便地看出哪一类型的等待事件消耗了最多的DB time时间,比如锁冲突,IO等待,进程间通信等。
2.3.5.6.9. 主机CPU使用统计¶
该报表显示快照期间主机CPU的使用情况,可以了解数据库实例的运行环境。当主机上没有其他进程消耗较大CPU的时候,该值可以近似地认为是数据库实例的CPU使用情况。该值可以跟OS的TOP命令做对比。
字段说明:
-
% User:用户态CPU时间的百分比
-
% Nice:低优先级用户态(Nice)CPU时间的百分比
-
% System:内核态CPU时间的百分比
-
% Wait IO:CPU等待IO时间(wait IO)的百分比
-
% Idle:CPU空闲等待时间的百分比
-
Begin Load Average:起始快照时刻CPU负载值(Load)
-
End Load Average:结束快照时刻CPU负载值(Load)
2.3.5.6.10. 主机IO使用统计¶
该报告显示主机上各磁盘IO读写统计数据,可以反映数据库实例所在环境的IO繁忙程度。
字段说明:
-
Device:磁盘设备名称,快照期间每个发生了IO读写的设备都有一行记录
-
Read Calls/s:每秒读次数
-
Read Size/s:每秒读大小
-
Read Time(s):IO读总时间,单位为秒
-
Write Calls/s:每秒写次数
-
Write Size/s:每秒写大小
-
Write Time(s):IO写总时间,单位为秒
2.3.5.6.11. 主机内存使用统计¶
该报表显示了主机内存在快照开始和结束时使用情况。
只有内存明显不够的情况下才需要关注,比如使用到了Swap交换空间。
字段说明:
-
Memory Total(MB):总共物理内存大小,单位为MB
-
Memory Used(MB):已经使用的物理内存大小,单位为MB
-
Memory Free(MB):剩余可用的物理内存大小,单位为MB
-
Swap Total(MB):Swap空间总大小,单位为MB
-
Swap Used(MB):Swap空间已经使用大小,单位为MB
-
Swap Free(MB):Swap空间剩余可用大小,单位为MB
-
Shared Memory(MB):共享内存的大小,单位为MB
2.3.5.6.12. 主机网络使用统计¶
该报告显示了主机上每个网络介质上网络IO的情况,如果网络负载高可以关注。
字段说明:
-
Interface:网络介质名称,每个网卡一行记录
-
IP Address:IP地址
-
Send Size/s:每秒发送/接收的字节数
-
Send Packets/s:每秒发送/接收的网络包数
-
Send Errors/s:每秒发送/接收数据时发送的错误数
-
Send Dropped/s:每秒发送/接收数据时因为错误而丢弃的网络包数
-
Send Size/s:每秒发送/接收的字节数
-
Send Packets/s:每秒发送/接收的网络包数
-
Send Errors/s:每秒发送/接收数据时发送的错误数
-
Send Dropped/s:每秒发送/接收数据时因为错误而丢弃的网络包数
2.3.5.6.13. 数据实例IO profile¶
数据库实例IO反映了快照期间共享/本地/临时数据块和WAL日志读写情况。如果有IO性能问题,需要关注。其中,WAL日志只统计写的情况,不统计读。
字段说明:
-
Metric:统计项
-
Read + Write Per Sec:每秒读写值
-
Read Per Sec:每秒读值
-
Write Per Sec:每秒写值
统计项说明:
-
Shared Blocks:共享块读写数
-
Shared Blocks (MB):共享块读写大小,单位为MB
-
Local Blocks:本地块读写数
-
Local Blocks (MB):本地块读写大小,单位为MB
-
Temp Blocks:临时块读写数
-
Temp Blocks (MB):临时块读写大小,单位为MB
-
WAL Size (MB):WAL写日志大小,单位为MB
重点关注每秒读写IO的大小,并和网络IO去比较,看看是不是IO遇到瓶颈了。另外,如果IO读写太高,需要分析一下业务场景,或者调整一下数据库的配置参数。
2.3.5.6.14. Top 10共享内存¶
通过该报告,能够知道共享内存主要由哪些部分组成,以及每部分的比例。
字段说明:
-
Shared Memory:共享内存块的名称
-
Begin Size:起始快照时刻,该共享内存块的大小
-
Begin %:起始快照时刻,该共享内存块占数据库实例全部共享内存的百分比
-
End Size:结束快照时刻,该共享内存块的大小
-
End %:结束快照时刻,该共享内存块占数据库实例全部共享内存的百分比
2.3.5.6.15. 查看报告主体¶
详细报告从更加细节的角度展示数据性能指标,主要包括:
1、 时间模型和等待事件
2、 TOP SQL统计
3、 数据库对象统计
4、 配置信息跟踪
2.3.5.6.16. 时间模型¶
该报表将DB Time分解为DB CPU和Wait Time(前台非空闲等待时间),并给出SQL解析、计划和执行时间,以及Idle Time(前台空闲等待时间)和后台等待时间。
字段说明:
-
Metric:统计项
-
Times(s):各统计项花费的总时间,单位为秒
-
% DB Time:各统计项花费时间占DB Time的百分比
统计项说明:
-
DB CPU:快照期间Backend进程执行SQL语句时花费在CPU上的时间
-
Wait Time:快照期间Backend进程执行SQL语句时发生的非空闲等待时间
-
Parse Time:快照期间Backend进程执行SQL语句时花在解析上的时间
-
Plan Time:快照期间Backend进程执行SQL语句时花在计划上的时间
-
Execute Time:快照期间Backend进程执行SQL语句时花在执行上的时间
-
DB Time:快照期间Backend进程执行SQL语句花费的总时间
-
Idle Time:快照期间Backend进程的空闲等待时间(不参与DB Time计算)
-
Background Wait Time:后台进程等待时间(不参与DB Time计算)
计算公式:
-
DB Time = FG Wait Time + DB CPU
-
Wait Time = FG Wait Time + FG Idle Time + BG Wait Time
2.3.5.6.17. 数据库DB Time¶
DB Time按照Database统计,显示在每个Database上的DB Time。通过该报告可以看到哪个数据库上花费的DB Time最多。
字段说明:
-
Message:报文名称
-
Calls:报文执行次数
-
Time(s):报文执行时间,单位为秒
-
Avg Time(ms):平均执行时间(Time / Calls)
-
% DB Time:报文执行时间占DB Time时间的百分比
2.3.5.6.18. SQL报文DB Time¶
DB Time按照SQL报文的类型统计,显示在每种报文类型上的DB Time。
一般说来说:如果Simple Query的报文占比高,说明语句没有使用SQL扩展协议。
字段说明:
-
Message:报文名称
-
Calls:报文执行次数
-
Time(s):报文执行时间,单位为秒
-
Avg Time(ms):平均执行时间(Time / Calls)
-
% DB Time:报文执行时间占DB Time时间的百分比
2.3.5.6.19. TOP SQL¶
这一部分共15张报表,从多个维度(DB Time,DB CPU,SQL执行次数,IO时间,共享数据块等)显示TOP SQL的时间占比和资源消耗情况。
除了最后一个Complete List Of SQL Text是显示SQL语句列表外,其他都是TOP SQL的各种排序和统计。
下面以 Top SQL By Elapsed Time 为例说明,该报表根据SQL语句的总体执行时间排序,显示了花费DB Time最多的前20条SQL语句的统计情况。
字段说明:
-
Query Hash:SQL语句对应的一个Hash值,在KWR报告里面能够唯一标识一条SQL语句(它由User Name、Database Name和Query字符串通过计算而来),点击它可以跳转到完整SQL列表的对应的SQL语句上
-
Elapsed Time(s):SQL语句总执行时间,单位为秒
-
Executions:SQL语句总执行次数
-
Elapsed Time/Exec(s):SQL语句平均每次执行时间,单位为秒
-
% Total:该SQL语句执行时间占全部SQL执行时间的百分比
-
% CPU:该SQL语句的CPU时间占该SQL语句总执行时间的百分比
-
% Wait:该SQL语句的非空暇等待时间占该SQL语句总执行时间的百分比
-
Query Text:该SQL语句前40个字符串,多于部分截断
具体调查某一条SQL语句的时候,还需要分析它涉及到的表和索引的统计信息,因为有时候性能问题往往是由部分热表、热索引冲突导致的。
可以通过点击Query Hash的链接跳转到Complete List Of SQL Text查看具体的SQL字符串:
2.3.5.6.20. 检查点和后台写统计¶
该报告主要来自sys_stat_bgwriter统计表,分两部分:
第一部分为checkpoint统计:
-
Scheduled checkpoints:已经被执行的计划中检查点的数量
-
Requested checkpoints:已经被执行的请求检查点的数量
-
Checkpoint write time (s):在文件被写入磁盘的检查点处理部分花费的总时间,单位为毫秒
-
Checkpoint sync time (s):在文件被同步到磁盘中的检查点处理部分花费的总时间,单位为毫秒
-
Checkpoints pages written:在检查点期间被写的缓冲区数目
第二部分为后台写统计:
-
Background pages written:被后台进程写的缓冲区数目
-
Backend pages written:被后端进程直接写的缓冲区数量
-
Backend fsync count:后端进程不得不直接执行fsync调用的次数
-
Bgwriter interrupts (too many buffers):后台写进程由于已经写了太多缓冲区而停止清洁扫描的次数
-
Number of buffers allocated:被分配的缓冲区数量
这些值可以除以快照期间过去的总秒数,得到平均每秒上发生的Checkpoint和Background Write的值,更加具有可比性。
2.3.5.6.21. Database统计¶
该报表上能够看到每个database对象上事务、IO读写、元组等统计结果。
字段说明:
-
database:数据库名
-
commits:提交的事务数
-
rollbacks:回滚的事务数
-
deadlocks:死锁次数
-
blocks read:物理读的blocks数
-
blocks hit:缓存命中的blocks数
-
blocks hit%:缓存命中的blocks百分比
-
tuples return:查询返回的元组数
-
tuples fetch:查询取出的元组数
-
tuples insert:查询插入的元组数
-
tuples update:查询更新的元组数
-
tuples delete:查询删除的元组数
2.3.5.6.22. 数据库对象统计¶
这部分主要是当前库的表、索引和用户自定义函数统计。
以Top Tables By Sequence Scan为例,它描述了当前库下关系表按照顺序扫描页数次数排序的统计结果:
字段说明:
-
Schema:关系表的Schema
-
Table:关系表名称
-
SeqScan:顺序扫描次数
-
Scan Pages:顺序扫描页数
-
Index Scan:关系表上发起的索引扫描次数
-
Index Fetch:被索引扫描取得的活着的行的数量
2.3.5.6.23. 配置信息跟踪¶
这部分记录了快照期间全部GUC参数的变更情况,如果有参数发了变化,都会记录下来,并在Nodes里记录变更的时间。
通过这个报告,在不需要收集客户环境的 kingbase.conf 情况下,就能查询到快照期间的每一个GUC参数的值。
2.3.6. 活跃会话历史报告SYS_KSH¶
sys_stat_activity里记录的等待事件是瞬时信息,没有对等待事件的时间进行累计,所以KingbaseES在V8R6中引入了明细会话历史(Kingbase Session History)和相应的报告工具。用户可以使用该工具进行会话历史的分析,并针对报告呈现的性能瓶颈进行优化。
sys_ksh以每秒采样的方式进行会话和数据收集,并将采集数据放入内存的Ringbuf队列中,采集的数据主要包括:会话、应用、等待事件、命令类型、QueryId等。其主要使用场景是:当前或历史某个时点,发生了什么样的异常,系统在执行/运行什么任务。
2.3.6.1. sys_ksh的配置¶
sys_ksh的参数在kingbase.conf中设置,典型用法可能是:
#kingbase.conf shared_preload_libraries ='sys_stat_statements, sys_ksh' sys_stat_statements'sys_stat_statements.max = 10000 sys_stat_statements.track =all sys_ksh.enable = on # default = off sys_ksh.ringbuf_size = 200000 # default = 100000 sys_ksh.history_days = 3 # default = 8
Note
采集报告需要在开启:track_activities,并至少设定sys_ksh.enable=on的情况下才可以查看。开启该参数会有一定的性能损耗。
2.3.6.2. sys_ksh采集数据说明¶
KSH采集的数据主要包括以下信息:
字段 | 类型 | 描述 |
---|---|---|
ts | timestamptz | 采样时间 |
db_id | oid | 数据库OID |
db_name | varchar(64) | 数据库名称 |
pid | int | 进程ID |
user_id | oid | 用户OID |
user_name | varchar(64) | 用户名 |
app_name | varchar(64) | 应用名称 |
client_addr | inet | 客户端IP地址 |
wait_class | text | 等待事件类型 |
wait_event | text | 等待事件 |
query_id | uint8 | QueryId |
backend_type | text | 后端类型,如:autovacuum, autovacuum worker等 |
type | text | 语句类型,如:INSERT, SELECT, UPDATE, DELETE, UTILITY |
phase | text | 执行阶段,如:PARSE, PLAN, EXECUTION, UNKNOWN |
state | text | 状态,如:IDLE, IDLE IN TRANSACTION, RUNNING等 |
2.3.6.3. 使用sys_ksh¶
创建KSH插件:
test=# Create extension sys_ksh;
保存于内存Ringbuf的数据可以通过视图perf.session_history查看:
test=# SELECT * FROM perf.session_history;
其中保存于数据库的历史数据可以通过视图perf.ksh_history查看:
test=# SELECT * FROM perf.ksh_history;
生成的报告可以通过perf.ksh_report查看:
test=# SELECT perf.ksh_report(start_ts, duration, slot_width, write_to_file);
参数说明:
-
start_ts: 报告开始时间,默认:当前时间-15分钟
-
duration: 报告时长,默认到15分钟,最大不超过60
-
slot_width: 报告最小区间,输入0时系统自动计算合适的宽度
-
write_to_file: 是否输出到sys_log目录,默认否
2.3.6.4. 查看sys_ksh报告¶
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: 区间活动统计
实例运行效果如下:
test=# SELECT * FROM perf.ksh_report('2020-08-24 18:50'::TIMESTAMPTZ, 10, 0, false); ksh_report ---------------------------------------------------------------------------- Report & Instance Info: + + Server Version:KingbaseES V008R006B0001 on x86_64-pc-linux-gnu + Listen Addresses:* + Input Begin Time:08-24 18:50:00 Input End Time:08-24 19:00:00 + Report Begin Time:08-24 18:50:37 Report End Time:08-24 18:56:05 + Sample Count:13538 + Seconds Count:328 + Avg Act Ses:41.27 + Data Source:Memory + + Top User Events: + ---------------------------------------------------------------------------+ Event Type Event Count Event% Avg Act Ses+ OnCPU CPU or Wait On CPU 7872 58.15 24.00+ LWLock wal_insert 2682 19.81 8.18+ Lock transactionid 1405 10.38 4.28+ LWLock buffer_content 486 3.59 1.48+ Client ClientRead 440 3.25 1.34+ IPC ProcArrayGroupUpdate 234 1.73 0.71+ Lock tuple 167 1.23 0.51+ Lock extend 131 0.97 0.40+ LWLock ProcArrayLock 57 0.42 0.17+ IPC ClogGroupUpdate 26 0.19 0.08+ + Top Background Events: + ---------------------------------------------------------------------------+ Event Type Event Count Event%+ + no data, skip section. + + Top SQL With Top Events: + ---------------------------------------------------------------------------+ Query Id Query Count Query% Top Event Event Count Event%+ 3040647352098461036 7 50.00 DataFileRead 7 100.00+ -1058555001657315210 6 42.86 CPU or Wait On CPU 3 50.00+ 8113479998896791651 1 7.14 CPU or Wait On CPU 1 100.00+ + Complete List Of SQL Text: + ---------------------------------------------------------------------------+ Query Id Mean Time(ms)+ 3040647352098461036 286.67+ select sys_prewarm($1) + + Query Id Mean Time(ms)+ -1058555001657315210 5.23+ SELECT count(*) AS low_stock FROM ( SELECT s_w_id, s_i_id, + s_quantity FROM bmsql_stock WHERE s_w_id + = $1 AND s_quantity < $2 AND s_i_id IN ( SELECT ol_i_id + FROM bmsql_district JOIN bmsql_order_line ON + ol_w_id = d_w_id AND ol_d_id = d_id AND ol_o_id >= + d_next_o_id - $5 AND ol_o_id < d_next_o_id WHERE + d_w_id = $3 AND d_id = $4 ) ) AS L + + Query Id Mean Time(ms)+ 8113479998896791651 1.98+ SELECT no_o_id FROM bmsql_new_order WHERE no_w_id = $1 + AND no_d_id = $2 ORDER BY no_o_id ASC + + Top Session: + ---------------------------------------------------------------------------+ SID SID% Top Event Event% App Name User Name+ 12462 1.61 CPU or Wait On CPU 41.28 Kingbase8 JDBC Driver benchmarksql+ + Top Client Id: + ---------------------------------------------------------------------------+ User Name App Name Event% Avg Act Ses+ benchmarksql Kingbase8 JDBC Driver 99.86 41.22+ linyu kingbase_*&+_ 0.14 0.06+ + Top SQL Command Type: + ---------------------------------------------------------------------------+ Cmd Type Dist Query Id Cmd % Avg Act Ses+ select 3 53.85 0.04+ utility 1 46.15 0.04+ + Top Phase Of Execution: + ---------------------------------------------------------------------------+ Phase Phase% Avg Act Ses+ execute 99.95 36.77+ plan 0.04 0.02+ parse 0.01 0.00+ + Activity Over Time: + ---------------------------------------------------------------------------+ Start End Slot Count Top Event Event Count Event%+ 18:50:37 18:51:00 15 DataFileRead 9 0.07+ CPU or Wait On CPU 6 0.04+ 18:51:00 18:52:00 2810 CPU or Wait On CPU 1273 9.40+ wal_insert 957 7.07+ transactionid 272 2.01+ 18:52:00 18:53:00 2817 CPU or Wait On CPU 1457 10.76+ wal_insert 739 5.46+ transactionid 283 2.09+ 18:53:00 18:54:00 2510 CPU or Wait On CPU 1597 11.80+ wal_insert 356 2.63+ transactionid 279 2.06+ 18:54:00 18:55:00 2607 CPU or Wait On CPU 1686 12.45+ wal_insert 325 2.40+ transactionid 275 2.03+ 18:55:00 18:56:00 2547 CPU or Wait On CPU 1681 12.42+ wal_insert 286 2.11+ transactionid 270 1.99+ 18:56:00 18:56:05 232 CPU or Wait On CPU 172 1.27+ transactionid 26 0.19+ wal_insert 19 0.14+ (1 row)
通过该输出,可以发现报告区间发生的最多的等待事件、查询和客户端的信息,基于这些信息可以帮助使用者快速定位当前系统的瓶颈点。
Note
-
该命令仅支持管理员在主服务器运行(备机无法运行)
-
历史数据的采样周期为10秒,实时数据的采样周期为1秒
-
报告的采集要求开启:track_activities和sys_stat_statements并设置sys_ksh = on
2.3.6.5. KWR和KSH比较¶
sys_kwr | sys_ksh | |
---|---|---|
定位 | 周期时间累积差异,查询特定时间段的累积变化 | 识别系统短暂(transient)变化,秒级时刻的实时值 |
原理 | 以累积式计数反馈系统在一定周期内的整体负载和瓶颈 | 基于时间的采样方式进行会话和数据收集 |
场景 | 本次系统升级后有哪些整体改进? 当前时段与基线相比指标如何变化 | 当前或历史某个时点,发生了什么样的异常,系统在执行/运行什么任务 |
数据留存 | 默认1小时采集,保留7天 | 默认1秒,实时数据保留1小时,过后以1/10的比例存入历史数据 |
2.3.7. 自动数据库性能监视器KDDM¶
KDDM是Kingbase ES实现性能自我诊断的工具,它依赖于KWR,因为KWR会定期的收集数据库系统在运行期间的性能统计数据。KDDM能够从数据库的整体配置和局部SQL方面给出一些优化建议。
2.3.7.1. KDDM参数¶
KDDM功能相关GUC参数包括:
sys_kddm.debug = false sys_kddm.language = chinese
参数的说明如下:
-
sys_kddm.debug:参数值true,false。默认值false。kddm调试开关,开启后显示完整的报告信息。
-
sys_kddm.language:参数值english,eng,chinese,chn。默认值chinese。设置输出kddm报告的语言。
2.3.7.2. 用户接口¶
TEXT perf.kddm_report( IN start_id integer, IN end_id integer)
功能:根据快照范围,生成kddm报告
参数:
start_id,开始快照ID
end_id,结束快照ID
返回值:TEXT格式的报告字符串
TEXT perf.kddm_report_to_file( IN start_id integer, IN end_id integer, IN file_path text)
功能:根据快照范围,生成kddm报告,并将报告保存到指定路径
参数:
start_id,开始快照ID
end_id,结束快照ID
file_path,报告保存路径(建议用全路径)
返回值:t - 保存成功,f - 保存失败
TEXT perf.kddm_sql_report( IN start_id integer, IN end_id integer, IN query_id bigint)
功能:根据快照范围和具体的SQL ID,给出SQL详细报告,主要用于分析耗时较多的 SQL 语句占用的CPU,IO资源的使用情况
参数:
start_id,开始快照ID
end_id,结束快照ID
query_id,SQL语句的ID
返回值:TEXT格式的SQL详细报告
TEXT perf.kddm_guc_advisor( IN conn bigint = 0, IN service_type TEXT = 'oltp', IN cpu bigint = 0, IN memory bigint = 0)
功能:给出默认配置参数建议值
参数:
conn:最大连接数,默认300,范围:1-1000
cpu:CPU核心数,默认自动获取,范围:1-1000
memory:内存大小,单位为MB,默认自动获取,范围:128MB-1T
service_type:业务类型,默认为’oltp’,可选范围:
oltp:事务型数据库服务器 olap:分析性数据库服务器 web:Web服务器 desktop:桌面应用 mixed:混合应用
返回值:默认配置建议字符串
2.3.7.3. 生成KDDM报告¶
首先要创建快照,详见《自动负载信息库SYS_KWR》中关于创建快照的步骤说明。有了快照之后就可以生成KDDM报告。
2.3.7.4. 查看KDDM报告¶
KDDM输出报告的内容章节包括:
-
建议列表
-
数据库时间分解
-
等待事件相关建议
-
TOP 等待事件建议
-
WAL 文件写锁冲突建议
-
存储 IO 分解
-
优化共享缓存建议
-
优化临时表缓存建议
-
优化工作缓存建议
-
优化检查点 IO 建议
-
优化 WAL IO 建议
-
优化 WAL 同步建议
-
使用文件预扩展建议
-
优化网络传输建议
-
优化网络丢包和错包建议
-
-
CPU相关建议
-
TOP SQL 建议
-
使用扩展SQL协议建议
-
CPU 负载过高建议
-
索引建议
-
优化回滚事务建议
-
堆页面裁剪建议
-
-
完整SQL列表
每条具体建议包含三项内容
-
建议依据:描述了数据库当前存在的性能问题。
-
建议动作:按优先级给出性能优化的建议操作,通过指定的操作选项能够改善当前存在的性能问题。
-
参考信息:描述了当前性能问题的具体指标。