Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

语句统计视图——pg_stat_statements

  • 属于 PostgreSQL 的扩展,配置方法如下:

    • 首先修改postgresql.conf

      #----------------------
      # PG_STAT_STATEMENTS OPTIONS
      #----------------------
      shared_preload_libraries = 'pg_stat_statements'
      custom_variable_classes = 'pg_stat_statements'
      pg_stat_statements.max = 1000
      pg_stat_statements.track = all
      
      • max 表示 最多记录1000条最耗时的语句
      • track 表示 追踪所有语句
    • 需要重启数据库集群

    • 然后手动创建

      CREATE EXTENSION pg_stat_statements;
      
  • pg_stat_statements 视图

    SELECT *
    FROM pg_stat_statements
    LIMIT 100;
    
    • 整体信息
      • userid 执行该语句的 用户 oid
      • dbid 执行该语句的 数据库 oid
      • queryid 内部哈希吗,由语句的解析树计算得来
      • query 语句的文本
    • 数量
      • calls 被执行的总次数
      • rows 该语句影响的总行数
    • 时间(单位 ms)
      • total_time 执行这类语句消耗的总时间
      • min_time 执行这类语句消耗最少的一次时间
      • max_time 执行这类语句消耗最多的一次时间
      • mean_time 执行这类语句消耗的平均时间
      • stddev_time 执行这类语句消耗的标准偏差时间
    • 共享块数
      • shared_blks_hit 该语句从 共享缓存 命中的块数
      • shared_blks_read 该语句从 共享块 读取的块数
      • shared_blks_dirtied 该语句 弄脏的共享块总数
      • shared_blks_written 该语句 写入的共享块总数
    • 本地块数
      • local_blks_hit 该语句 本地缓存 命中的块数
      • local_blks_read 该语句从 本地块 读取的块数
      • local_blks_dirtied 该语句 弄脏的本地块总数
      • local_blks_written 该语句 写入的本地块总数
    • 临时块数
      • temp_blks_read 该语句从 临时块 读取的块数
      • temp_blks_written 该语句 写入的临时块总数
    • 时间(单位 ms)
      • 下面两个,需要 track_io_timing 被启用 才能生效,否则为 0
      • blk_read_time 该语句 读取块 消耗的总时间
      • blk_write_time 该语句 写入块 消耗的总时间
  • 找出调用次数多+平均耗时较长的语句

    • 粗略查询
      SELECT  query, calls, total_time,
          (total_time/calls) as average ,rows,
          100.0 * shared_blks_hit /nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent
      FROM pg_stat_statements
      ORDER BY average DESC LIMIT 100;
      
      • 前 100 条
        • 包含 语句、调用次数、消耗总时间、平均耗时、涉及行、共享缓存命中率
        • 按照平均耗时排序
    • 精确查询
      SELECT  query, calls, total_time,
          (total_time/calls) as average ,rows,
          100.0 * shared_blks_hit /nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent
      FROM pg_stat_statements
      WHERE calls > 100000 AND (total_time/calls) > 5
      ORDER BY total_time DESC LIMIT 300;
      
      • 前 300 条
        • 包含同上
        • 增加筛选条件: 日均调用 3 万次(这里记录了 8 天的量),语句平均耗时大于 5ms
        • 按照消耗总时间排序
  • 找出造成大量磁盘 IO 的语句

    • 精确查询
      SELECT *
      FROM pg_stat_statements
      ORDER BY shared_blks_read DESC
      LIMIT 200;
      
      • 前 100 条
        • 包含 所有项目
        • 按照共享块读取量排序
  • 清零

    SELECT pg_stat_statements_reset();