暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL中所有关于 pg_stat_statements

原创 Handsome BOY 2022-10-12
3387

几乎所有使用 PostgreSQL 的人,以及 YugabyteDB 的用户,都在使用 pg_stat_statements 来查看历史执行情况。然而,有很多人一直在想一些事情,这就是这篇博文的内容。

首先是关于 pg_stat_statements 本身。Pg_stat_statements 是一个扩展,而不是核心数据库的一部分。然而,它是一个所谓的“contrib 扩展”,它随 postgres 源代码一起提供。pg_stat_statements 的功能位于一个名为 pg_stat_statements.so 的库中,并且必须将 postgres 配置为通过设置加载该库shared_preload_libraries

postgres 中扩展的工作方式非常有趣,尽管超出了本文的范围,无法深入挖掘。postgres 可执行代码包含“钩子”,它允许诸如 pg_stat_statements 之类的扩展将自身附加到,这意味着当 postgres 执行触发这样的钩子时,扩展功能会被触发/执行。

配置

pg_stat_statements 在服务器启动时分配固定数量的共享内存来分配状态结构和哈希表。这可以是固定大小的分配,因为 pg_stat_statements 将 SQL 文本存储在文件中,并将偏移量存储在哈希表中。

pg_stat_statements 可以存储的语句数量设置pg_stat_statements.max为默认设置为 5000。

默认情况下,pg_stat_statements 将 statements 数据保存到文件中,因此信息通过服务器停止和启动保存。此行为由 设置pg_stat_statements.saveon默认情况下。

pg_stat_statements 可以通过设置以下列方式配置跟踪语句pg_stat_statements.track

  • none: 不跟踪任何语句。
  • top:(默认)仅跟踪“顶级语句”。这意味着不会跟踪 SQL 内部函数和过程。
  • all:这会跟踪所有语句,包括“嵌套”语句。

如果您正在调整或调查使用函数和/或过程的数据库,则设置pg_stat_statements.trackall对于查看在函数和过程中执行的 SQL 非常有用。

默认情况下,pg_stat_statements 还跟踪所谓的“实用程序”语句,这些语句是 SELECT、INSERT、UPDATE 和 DELETE 之外的语句。这可以通过设置pg_stat_statements.track_utility来更改off

SQL

pg_stat_statements 处理 SQL 文本的方式需要理解以使用 pg_stat_statements。

首先:如果执行未成功完成,则执行不会记录在 pg_stat_statements 中,尽管可能已经完成了大量工作。

当一条语句被放入 pg_stat_statements 哈希表时,它会尝试对等价的查询/语句进行分组。为此, pg_stat_statements 使用哈希键:

typedef struct pgssHashKey
{
    Oid         userid;         /* user OID */
    Oid         dbid;           /* database OID */
    uint64      queryid;        /* query identifier */
} pgssHashKey;
复制

这表明,除了查询 ID,任何语句都由用户 OID 和数据库 OID 唯一标识。因此,使用另一个用户执行的真正相同的 SQL 将在 pg_stat_statements 中生成自己的语句。该语句由查询标识符标识。

此查询标识符以一种有趣的方式生成,因此了解它的计算方式很有用。简而言之,查询是规范化的,postgres 内部将其称为“查询混杂”,这意味着它解析查询树节点的基本字段并生成 64 位哈希,存储为查询标识符。因为查询树存储 OID,文本中相同的查询,但具有不同的 OID,将生成不同的查询标识符。

如果创建了一个新的 pg_stat_statements 条目,也就是找不到生成的哈希键时,pg_stat_statements 将获取查询文本并创建它的“代表性查询”,这意味着常量被替换为参数符号(“$n”)。这意味着布局和 SQL 文本中的任何额外注释都将保留并存储在 pg_stat_statements 条目创建时间。在创建 pg_stat_statements 条目后成功执行的任何生成相同哈希键的查询都将更改(添加到)统计信息,但不会更改查询文本。

pg_stat_statements 中的查询文本未更改可能会令人困惑,例如第一次执行包含稍后更改的提示:提示不参与生成查询 id 的查询混乱,因此更改的提示将生成相同的查询 id,因此在这种情况下执行将添加到 pg_stat_statements 查询,该查询显示当查询添加到 pg_stat_statements 时的原始提示。显然,这需要使用 postgres pg_hint_plan 扩展,核心 postgres 不支持提示。

链接 pg_stat_activity.query 与 pg_stat_statements.query

视图 pg_stat_activity 显示当前活动,包括原始/未更改的查询文本(最多 1024 个字节)。当查询添加到 pg_stat_statements 时,原始查询文本将更改为“代表性查询”查询文本。

这意味着查询文本不能用于将 pg_stat_activity 中的查询映射到 pg_stat_statements 中的查询。事实上,直到 postgres 版本 13,没有办法获得 pg_stat_activity 和 pg_stat_statements 之间的查询相同的绝对证明。在版本 14 中,pg_stat_activity 使用 query_id 列进行了改进,它允许 postgres 计算查询 id,这是我知道的在 pg_stat_activity 和 pg_stat_statements 之间链接查询的唯一方法。

查询时间

在低于版本 13 的 PostgreSQL 版本中,pg_stat_statements 保留“total_time”,以及它的统计推导,例如 min/max/avg/stddev 时间。这(可悲)不是实际的查询总时间。这个时间是在 postgres 语句的执行阶段花费的时间,因此不包括解析、重写和计划阶段。

在 PostgreSQL 13 及更高版本中,pg_stat_statements 更清楚地说明了时序包括哪些内容,并称时序为 'total_plan_time' 和 'total_exec_time',更明显。请注意,这意味着它仍然没有跟踪完整的查询时间,其中包括解析和重写阶段。

重置 pg_stat_statements

使用可以使用 调用的 pg_stat_statements_reset() 函数,select pg_stat_statements_reset();可以清空/重置 pg_stat_statements 视图。

原文标题:All about pg_stat_statements

原文作者:Frits Hoogland 

原文链接:https://dev.to/yugabyte/all-about-pgstatstatements-27jn


「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论