zoukankan      html  css  js  c++  java
  • pg的sql统计信息,慢查询等

    背景

    数据库运维过程中,dba都比较关注sql的执行时间。研发在数据库应用开发上,速度慢的sql比比皆是,很多速度很慢都是sql写得不好,效率不高,执行过程中也会造成数据库的负载过大。比如无用的去重,无效的条件,不必要的子查询,sql用不上的索引。而对于这些不符合要求的sql,首先要去把这些sql找出来。

    措施

    pg数据库提供了统计信息的功能来查找,下面介绍两种办法:

    • 修改日志参数,记录超过指定时间的sql,以及当时的执行时间
    • 通过pg_stat_statements统计

    修改日志参数

    log_min_duration_statement:从log中找出执行超过一定时间的sql。这个参数是设置执行最小多长时间的sql输出到log,例如输出执行超过3秒的sql,可以设置log_min_duration_statement = 3s。这个参数设置为-1是无效,默认为-1。设置为0是输出所有的sql,但这样会增加服务器的负担,一般不要设置太低的值。

    auto_explain功能:在Postgresql8.4版本后新增了该功能。默认这个功能是不可用的,需要配置如下。这样系统在执行的时候遇到超过2秒的SQL的话,,会自动把sql输出到log,这样看log就更容易找到问题点了。

    shared_preload_libraries = 'auto_explain'
    custom_variable_classes = 'auto_explain'   #PostgreSQL9.2版本后此参数已取消,不需要设置
    auto_explain.log_min_duration = 2s
    

    实际log查看:

    < 2019-11-12 15:40:30.284 CST > 日志:  执行时间: 3048.397 ms 语句: SELECT * FROM indexedresult WHERE searchtitle LIKE '%好%' ORDER BY  searchtitle
    

    加载pg_stat_statements模块

    pg_stat_statements模块提供了一种方法,用于跟踪所有由服务器执行的sql语句的统计,例如,语句总调用次数,总执行时间,从内存中读取的块数,从磁盘读取的块数等信息。在添加或删除模块pg_stat_statements模块时,需要额外的共享内存,所以必须重启数据库。pg_stat_statements模块加载会消耗部分的内存,可以通过pg_stat_statements.max * track_activity_query_size来计算。这个值是比较小的,假如pg_stat_statements.max 值为 10000, track_activity_query_size值为4096,也就消耗了40M内存。

    参考配置如下:

    shared_preload_libraries = 'pg_stat_statements '
    track_activity_query_size = 4096                #SQL文本的最大大小,4K
    custom_variable_classes = 'pg_stat_statements '  #PostgreSQL9.2版本后此参数已取消,不需要设置
    pg_stat_statements.max = 10000                #跟踪模块中的语句的最大数目
    pg_stat_statements.track = all
    

    参数配置好后,需要重启数据库。注意该模块是区分数据库的,不是全局共享的。如果无法查询,可能需要在对应的数据库下面加载pg_stat_statements模块。运行如下语句:

    CREATE EXTENSION pg_stat_statements;
    

    配置好pg_stat_statements模块后,经过一段时间的运行,我们就可以通过pg_stat_statements视图来统计效率低的SQL,语句如下:

    --查询语句总调用次数大于10次,平均运行时间倒序的SQL
    SELECT t.userid,
            t.dbid,
            t.query || ';',
            t.calls,
            t.total_time,
            t.rows,
            t.total_time / t.calls
      FROM pg_stat_statements t
     WHERE (t.calls IS NOT NULL OR t.calls <> 0)
       AND t.query !~ '^COPY|<insufficient privilege'
       AND t.calls > 10
     ORDER BY 7 DESC;
    
    

    总结

    上面两种方法可以根据实际业务需要来进行,比如仅仅需要查看问题sql的情况可以用第一种,如果需要深入分析sql的类别,执行次数,执行时间等更丰富的信息可以采用第二种方式,根据调用的次数来设计缓存也是非常重要的依据。

  • 相关阅读:
    hdu 2647 Reward
    hdu 2094 产生冠军
    hdu 3342 Legal or Not
    hdu 1285 确定比赛名次
    hdu 3006 The Number of set
    hdu 1429 胜利大逃亡(续)
    UVA 146 ID Codes
    UVA 131 The Psychic Poker Player
    洛谷 P2491消防 解题报告
    洛谷 P2587 [ZJOI2008]泡泡堂 解题报告
  • 原文地址:https://www.cnblogs.com/easonbook/p/11843716.html
Copyright © 2011-2022 走看看