PostgreSQL 慢查询SQL跟踪操作
PostgreSQL开启慢SQL捕获在排查问题时是个很有效的手段。根据慢SQL让我在工作中真正解决了实际问题,很有帮助。
PostgreSQL日志支持的输出格式有stderr(默认)、csvlog、syslog
一般的错误跟踪,只需在配置文件【postgresql.conf】简单设置几个参数,当然还有错误级别等要设置。
logging_collector=on log_destination='stderr' log_directory='log' log_filename='postgresql-%Y-%m-%d_%H%M%S.log' SELECT name, setting, vartype, boot_val, reset_val FROMpg_settings wherenamein('logging_collector','log_destination','log_directory','log_filename');
默认的跟踪日志记录在pgdate/log中,如/usr/local/pgsql/data/log。
其他几个重要参数说明:
log_rotation_age=1440#minute,多长时间创建新的文件记录日志。0表示禁扩展。 log_rotation_size=10240#kb,文件多大后创建新的文件记录日志。0表示禁扩展。 log_truncate_on_rotation=on#可重用同名日志文件
当需要跟踪SQL语句或者慢语句,得需要设置以下参数:
log_statement=all#需设置跟踪所有语句,否则只能跟踪出错信息 log_min_duration_statement=5000#milliseconds,记录执行5秒及以上的语句
log_statement:
设置跟踪的语句类型,有4种类型:none(默认),ddl,mod,all。跟踪所有语句时可设置为"all"。
log_min_duration_statement:
跟踪慢查询语句,单位为毫秒。如设置5000,表示日志将记录执行5秒以上的SQL语句。
当log_statement=all和log_min_duration_statement同时设置时,将跟踪所有语句,忽略log_min_duration_statement设置。所以需按情况设置其中一个或两个值。
加载配置
selectpg_reload_conf(); showlog_min_duration_statement;
针对某个用户或者某数据库进行设置
alterdatabasetestsetlog_min_duration_statement=5000;
捕获正在查询的慢SQL
select*frompg_stat_activitywherestate<>'idle'andnow()-query_start>interval'5s'orderbyquery_start;
补充:PostgreSQLCPU占用100%性能分析及慢sql优化
查看连接数变化
CPU利用率到达100%,首先怀疑,是不是业务高峰活跃连接陡增,而数据库预留的资源不足造成的结果。我们需要查看下,问题发生时,活跃的连接数是否比平时多很多。
对于RDSforPG,数据库上的连接数变化,可以从控制台的监控信息中看到。而当前活跃的连接数>可以直接连接数据库,使用下列查询语句得到:
selectcount(*)frompg_stat_activitywherestatenotlike'%idle';
追踪慢SQL
如果活跃连接数的变化处于正常范围,则很大概率可能是当时有性能很差的SQL被大量执行导致。由于RDS有慢SQL日志,我们可以通过这个日志,定位到当时比较耗时的SQL来进一步做分析。但通常问题发生时,整个系统都处于停滞状态,所有SQL都慢下来,当时记录的>慢SQL可能非常多,并不容易排查罪魁祸首。这里我们介绍几种在问题发生时,即介入追查慢SQL的方法。
1、第一种方法是使用pg_stat_statements插件定位慢SQL,步骤如下。
1.1如果没有创建这个插件,需要手动创建。我们要利用插件和数据库系统里面的计数信息(如SQL执行时间累积等),而这些信息是不断累积的,包含了历史信息。为了更方便的排查当前的CPU满问题,我们要先重置计数器。
createextensionpg_stat_statements; selectpg_stat_reset(); selectpg_stat_statements_reset();
1.2等待一段时间(例如1分钟),使计数器积累足够的信息。
1.3查询最耗时的SQL(一般就是导致问题的直接原因)。
select*frompg_stat_statementsorderbytotal_timedesclimit5;
1.4查询读取Buffer次数最多的SQL,这些SQL可能由于所查询的数据没有索引,而导致了过多的Buffer读,也同时大量消耗了CPU。
select*frompg_stat_statementsorderbyshared_blks_hit+shared_blks_readdesclimit5;
2、第二种方法是,直接通过pg_stat_activity视图,利用下面的查询,查看当前长时间执行,一直不结束的SQL。这些SQL对应造成CPU满,也有直接嫌疑。
selectdatname,usename,client_addr,application_name,state,backend_start,xact_start,xact_stay,query_start,query_stay,replace(query,chr(10),'')asqueryfrom(selectpgsa.datnameasdatname,pgsa.usenameasusename,pgsa.client_addrclient_addr,pgsa.application_nameasapplication_name,pgsa.stateasstate,pgsa.backend_startasbackend_start,pgsa.xact_startasxact_start,extract(epochfrom(now()-pgsa.xact_start))asxact_stay,pgsa.query_startasquery_start,extract(epochfrom(now()-pgsa.query_start))asquery_stay,pgsa.queryasqueryfrompg_stat_activityaspgsawherepgsa.state!='idle'andpgsa.state!='idleintransaction'andpgsa.state!='idleintransaction(aborted)')idleconnectionsorderbyquery_staydesclimit5;
datname|usename|client_addr|application_name|state|backend_start|xact_start|xact_stay|query_start|query_stay| query ---------+-------------+---------------+--------------------------+--------+-------------------------------+-------------------------------+---------------+-------------------------------+---------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- denali|denaliadmin|10.222.16.45|pgAdminIII-QueryTool|active|2018-02-2622:36:05.603781+00|2018-02-2622:36:13.054396+00|187614.245395|2018-02-2622:36:13.054396+00|187614.245395|select*fromgen3_search_eu_17q2_20171115_epl.place_name\rwhereplace_idnotin(selectplace_idfromgen3_search_eu_17q1_20170308_epl.place_name)\randnamenotin(selectnamefromgen3_search_eu_17q1_20170308_epl.place_name)\randlang='ENG'\rlimit50 denali|denaliadmin|10.222.16.45|pgAdminIII-QueryTool|active|2018-02-2623:46:24.442846+00|2018-02-2623:46:34.920261+00|183392.37953|2018-02-2623:46:34.920261+00|183392.37953|select*fromgen3_search_eu_17q2_20171115_epl.place_name\rwhereplace_idnotin(selectplace_idfromgen3_search_eu_17q1_20170308_epl.place_name)\randnamenotin(selectnamefromgen3_search_eu_17q1_20170308_epl.place_name)\randlang='ENG'\rlimit50\r denali|denaliadmin|10.222.16.45|pgAdminIII-QueryTool|active|2018-02-2701:19:53.83589+00|2018-02-2701:20:01.519778+00|177785.780013|2018-02-2701:20:01.519778+00|177785.780013|select*fromgen3_search_eu_17q2_20171115_epl.place_name\rwhereplace_idnotin(selectplace_idfromgen3_search_eu_17q1_20170308_epl.place_name)\randnamenotin(selectnamefromgen3_search_eu_17q1_20170308_epl.place_name)\rlimit50 denali|denaliadmin|10.222.16.45|pgAdminIII-QueryTool|active|2018-02-2701:46:05.207888+00|2018-02-2701:47:52.039779+00|176115.260012|2018-02-2701:47:52.039779+00|176115.260012|selecta.place_id,a.metadata_dictionary_id,a.value,a.lang,b.place_id,b.metadata_dictionary_id,b.value,b.lang\rfromgen3_search_eu_17q1_20170308_epl.place_addressa\rinnerjoingen3_search_eu_17q2_20171115_epl.place_addressb\rona.place_id=b.place_id\rwherea.metadata_dictionary_id=b.metadata_dictionary_idanda.lang=b.langanda.value!=b.valueandb.place_idnotin(selectpoi_idfromgen3_search_eu_17q2_20171115_epl.place_embeded_ids)\rlimit100\r denali|denaliadmin|10.224.14.148|pgAdminIII-QueryTool|active|2018-02-2705:05:39.903885+00|2018-02-2705:05:48.827779+00|164238.472012|2018-02-2705:05:48.827779+00|164238.472012|selecta.place_id,a.metadata_dictionary_id,a.value,a.lang,b.place_id,b.metadata_dictionary_id,b.value,b.lang\rfromgen3_search_eu_17q1_20170308_epl.place_addressa\rinnerjoingen3_search_eu_17q2_20171115_epl.place_addressb\rona.place_id=b.place_id\rwherea.metadata_dictionary_id=b.metadata_dictionary_idanda.lang=b.langanda.value!=b.valueandb.place_idnotin(selectpoi_idfromgen3_search_eu_17q2_20171115_epl.place_embeded_ids)\rlimit100\r (5rows)
3、第3种方法,是从数据表上表扫描(TableScan)的信息开始查起,查找缺失索引的表。数据表如果缺失索引,大部分热数据又都在内存时(例如内存8G,热数据6G),此时数据库只能使用表扫描,并需要处理已在内存中的大量的无关记录,而耗费大量CPU。特别是对于表记录数超100的表,一次表扫描占用大量CPU(基本把一个CPU占满),多个连接并发(例如上百连接),把所有CPU占满。
3.1通过下面的查询,查出使用表扫描最多的表:
select*frompg_stat_user_tableswheren_live_tup>100000andseq_scan>0orderbyseq_tup_readdesclimit10;
3.2查询当前正在运行的访问到上述表的慢查询:
select*frompg_stat_activitywherequeryilike'%%'andquery_start-now()>interval'10seconds';
3.3也可以通过pg_stat_statements插件定位涉及到这些表的查询:
select*frompg_stat_statementswherequeryilike'%