[英]Postgresql query is performing really bad
我在Postgresql数据库中查询性能存在巨大问题。 postgresql的版本为: "PostgreSQL 8.4.3 on x86_64-unknown-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20070115 (prerelease) (SUSE Linux), 64-bit"
我的配置文件设置如下:
shared_buffers = 8GB
effective_cache_size = 24GB
work_mem = 419430kB
maintenance_work_mem = 2GB
checkpoint_segments = 128
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 500
constraint_exclusion = on
我需要执行的查询是:
SELECT events.evt_id, events.evt_time, events.device_evt_time , to_ip_char(events.sip) , evt_agent.port , events.rv40 , events.evt , events.msg , events.sun , events.rv35 , events.dun , events.rv45 , events.fn , events.dp , events.trgt_trust_name , events.trgt_trust_domain , events.rv36 , events.rv43 , events.cv21 , events.cv40 , events.cv41 , events.cv42 , events.cv43 , events.cv44 , events.cv50 , events.cv51 , events.cv52 , events.cv53 , events.cv54 , events.cv55 , events.cv56 , events.cv35 , events.cv60 , events.cv61 , events.cv62
FROM events, evt_agent
WHERE
events.agent_id = evt_agent.agent_id AND (evt_agent.port::text = ANY (ARRAY['x'::character varying, 'y'::character varying, 'z'::character varying]::text[]))
AND events.evt::text <> 'Internal Message'::text
AND event_time > '2015-12-31 13:23:55.767+00'::timestamptz limit 10;
ORDER BY events.evt_time;
表事件是一个分区表,每天一个分区。 每个分区都有两个约束:
Name events_p_YYYYMMDDHHMISS_events_p_max_pk
Columns evt_time, evt_id
Name events_p_YYYYMMDDHHMISS_dc
Definition evt_time > '2015-12-04 13:24:25.267973+00'::timestamp with time zone AND evt_time <= '2015-12-05 13:24:25.267973+00'::timestamp with time zone
和七个索引:
Name events_p_YYYYMMDDHHMISS_events_p_max_identity_ix1
Columns evt_time, init_usr_identity_guid, rid02
Operator classes timestamptz_ops, uuid_ops, int8_ops
Name events_p_YYYYMMDDHHMISS_events_p_max_identity_ix2
Columns evt_time, trgt_usr_identity_guid, rid02
Operator classes timestamptz_ops, uuid_ops, int8_ops
Name events_p_YYYYMMDDHHMISS_events_p_max_ix1
Columns evt_time, sev, agent_id
Operator classes timestamptz_ops, int4_ops, int8_ops
Name events_p_YYYYMMDDHHMISS_events_p_max_ix2
Columns evt_time, dip, sev
Operator classes timestamptz_ops, int4_ops, int4_ops
Name events_p_YYYYMMDDHHMISS_events_p_max_ix3
Columns evt_time, res, sev
Operator classes timestamptz_ops, text_ops, int4_ops
Name events_p_YYYYMMDDHHMISS_events_p_max_ix4
Columns evt_time, sip, sev
Operator classes timestamptz_ops, int4_ops, int4_ops
Name events_p_YYYYMMDDHHMISS_events_p_max_ix5
Columns evt_time, txnmy_id, agent_id
Operator classes timestamptz_ops, int8_ops, int8_ops
表evt_agent是仅包含约20-30行的字典表。
限制:
Name evt_agent_pk
Columns agent_id
指标:
Name evt_agent_ak1
Columns agent, port, rn, pn, sn, st, device_ctgry, src_id, cust_id
Operator classes text_ops, text_ops, text_ops, text_ops, text_ops, text_ops, text_ops, uuid_ops, int8_ops
Name evt_agent_ix1
Columns device_ctgry, agent_id
Operator classes text_ops, int8_ops
当我执行查询时,我得到了这个解释计划: http : //explain.depesz.com/s/3xcu
Name evt_agent_ix2
Columns st, agent_id
Operator classes text_ops, int8_ops
Name test_ev_ag_indx1
Columns agent_id
Operator classes int8_ops
我认为统计信息存在问题,因此我对所有相关表进行了“真空分析”,但查询性能没有得到改善,没有说明计划。
我尝试使用“内部查询”技巧,在这里说明计划: http : //explain.depesz.com/s/FAkH
据我了解,情况变得更糟。
您是否知道如何为该查询获得更好的执行计划? 现在,大约需要42分钟才能从查询中获取任何结果。
提前致谢!
我们将不得不尝试消除哈希联接。 横向连接可能只是答案:
SELECT events.evt_id, events.evt_time, events.device_evt_time , to_ip_char(events.sip) , evt_agent.port , events.rv40 , events.evt , events.msg , events.sun , events.rv35 , events.dun , events.rv45 , events.fn , events.dp , events.trgt_trust_name , events.trgt_trust_domain , events.rv36 , events.rv43 , events.cv21 , events.cv40 , events.cv41 , events.cv42 , events.cv43 , events.cv44 , events.cv50 , events.cv51 , events.cv52 , events.cv53 , events.cv54 , events.cv55 , events.cv56 , events.cv35 , events.cv60 , events.cv61 , events.cv62
FROM evt_agent,
LATERAL (SELECT *
FROM events AS e
WHERE
e.agent_id = evt_agent.agent_id
AND e.evt::text <> 'Internal Message'::text
AND e.event_time > '2015-12-31 13:23:55.767+00'::timestamptz
LIMIT 10000) AS events
WHERE (evt_agent.port::text = ANY (ARRAY['x'::character varying, 'y'::character varying, 'z'::character varying]::text[]))
ORDER BY events.evt_time
LIMIT 10000;
请在没有内部限制的情况下尝试使用此方法,然后发布两者的说明计划。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.