如何解决 Amazon Redshift 中的集群或查询性能问题?
我想解决我的 Amazon Redshift 集群中的查询性能问题或提高其查询性能。
简短描述
如果您在 Amazon Redshift 集群中遇到性能问题,请完成以下任务:
- 监控您的集群性能指标。
- 查看 Amazon Redshift Advisor 的建议。
- 查看查询执行警报以及是否存在磁盘使用率过高。
- 检查是否存在锁定问题和长时间运行的会话或事务。
- 检查您的工作负载管理 (WLM) 配置。
- 检查您的集群节点硬件维护和性能。
解决方法
监控您的集群性能指标
查看您的集群性能指标和图表,以帮助您找到性能下降的根本原因。查看 Amazon Redshift 控制台中的性能数据,比较一段时间内的集群性能。
这些指标的增加可能表明您的 Amazon Redshift 集群上的工作负载和资源争用增加。有关详细信息,请参阅使用 Amazon CloudWatch 指标监控 Amazon Redshift。
查看 Amazon Redshift 控制台中的工作负载执行明细,以检查特定的查询和运行时。例如,如果您看到查询计划时间增加,则表明查询可能正在等待锁定。
查看 Amazon Redshift Advisor 的建议
使用Amazon Redshift Advisor 的建议了解您的集群可能需要改进之处。这些建议基于常见使用模式和 Amazon Redshift 最佳实践。
查看查询执行警报以及是否存在磁盘使用率过高
当查询运行时,Amazon Redshift 会记录查询性能并指明查询是否高效运行。如果确定查询效率低下,Amazon Redshift 会记录查询 ID,并给出查询性能改进建议。这些建议记录在 STL_ALERT_EVENT_LOG 内部系统表中。
如果您遇到查询缓慢或效率低下的情况,请检查 STL_ALERT_EVENT_LOG 条目。要从 STL_ALERT_EVENT_LOG 表中检索信息,请运行以下查询:
SELECT TRIM(s.perm_table_name) AS TABLE , (SUM(ABS(DATEDIFF(SECONDS, Coalesce(b.starttime, d.starttime, s.starttime), CASE WHEN COALESCE(b.endtime, d.endtime, s.endtime) > COALESCE(b.starttime, d.starttime, s.starttime) THEN COALESCE(b.endtime, d.endtime, s.endtime) ELSE COALESCE(b.starttime, d.starttime, s.starttime) END))) / 60)::NUMERIC(24, 0) AS minutes , SUM(COALESCE(b.ROWS, d.ROWS, s.ROWS)) AS ROWS , TRIM(SPLIT_PART(l.event, ':', 1)) AS event , SUBSTRING(TRIM(l.solution), 1, 60) AS solution , MAX(l.QUERY) AS sample_query , COUNT(DISTINCT l.QUERY) FROM STL_ALERT_EVENT_LOG AS l LEFT JOIN stl_scan AS s ON s.QUERY = l.QUERY AND s.slice = l.slice AND s.segment = l.segment LEFT JOIN stl_dist AS d ON d.QUERY = l.QUERY AND d.slice = l.slice AND d.segment = l.segment LEFT JOIN stl_bcast AS b ON b.QUERY = l.QUERY AND b.slice = l.slice AND b.segment = l.segment WHERE l.userid > 1 AND l.event_time >= DATEADD(DAY, -7, CURRENT_DATE) GROUP BY 1, 4, 5 ORDER BY 2 DESC, 6 DESC;
该查询会列出查询 ID 以及集群上运行的查询的最常见问题和问题发生次数。
以下是描述触发警报原因的查询和信息的输出示例:
table | minutes | rows | event | solution | sample_query | count-------+---------+------+------------------------------------+--------------------------------------------------------+--------------+------- NULL | NULL | NULL | Nested Loop Join in the query plan | Review the join predicates to avoid Cartesian products | 1080906 | 2
要查看查询性能,请检查查询优化的诊断查询。确保您的查询操作经过精心设计,可以高效运行。例如,并非所有的 JOIN 操作都有效。嵌套循环 JOIN 是效果最差的 JOIN 类型。由于嵌套循环 JOIN 会显著增加查询运行时间,因此要尽量避免嵌套循环。
为了帮助您诊断问题,请找出执行嵌套循环的查询。有关更多信息,请参阅如何使用 Amazon Redshift 解决磁盘使用率过高或已满的问题?
检查是否存在锁定问题和长时间运行的会话或事务
在集群上运行查询之前,Amazon Redshift 可能会在查询运行中涉及的表上获取表级锁。有时,查询似乎没有响应,或者查询运行时出现峰值。如果您的查询运行时出现峰值,则锁定问题可能是导致峰值的原因。有关更多信息,请参阅为什么我在 Amazon Redshift 中的查询计划时间如此高?
如果您的表当前被另一个进程或查询锁定,则您的查询会无法继续。因此,在 STV_INFLIGHT 表中是看不到您的查询的。相反,STV_RECENTS 表中会显示您正在运行的查询。
有时,长时间运行的事务可能会导致查询停止响应。请采取以下措施,以免长时间运行的会话或事务影响您的查询性能:
- 使用 STL_SESSIONS 和 SVV_TRANSACTIONS 表来检查是否存在长时间运行的会话和事务,然后终止它们。
- 设计查询时,要考虑到让 Amazon Redshift 能够快速高效地处理查询。
**注意:**长时间运行的会话或事务还会影响回收磁盘空间的 VACUUM 操作,并导致虚影行或未提交的行数增加。查询扫描的虚影行可能会影响查询性能。
有关更多信息,请参阅如何在 Amazon Redshift 中检测和释放锁定?
检查您的 WLM 配置
根据您的 WLM 配置,查询可能会立即开始运行或查询一段时间。最大限度地减少排队运行查询的时间。要定义队列,请检查您的 WLM 内存分配。
要在几天内检查集群的 WLM 队列,请运行以下查询:
SELECT *, pct_compile_time + pct_wlm_queue_time + pct_exec_only_time + pct_commit_queue_time + pct_commit_time AS total_pcntFROM (SELECT IQ.*, ((IQ.total_compile_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) AS pct_compile_time, ((IQ.wlm_queue_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) AS pct_wlm_queue_time, ((IQ.exec_only_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) AS pct_exec_only_time, ((IQ.commit_queue_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) pct_commit_queue_time, ((IQ.commit_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) pct_commit_time FROM (SELECT trunc(d.service_class_start_time) AS DAY, d.service_class, d.node, COUNT(DISTINCT d.xid) AS count_all_xid, COUNT(DISTINCT d.xid) -COUNT(DISTINCT c.xid) AS count_readonly_xid, COUNT(DISTINCT c.xid) AS count_commit_xid, SUM(compile_us) AS total_compile_time, SUM(datediff (us,CASE WHEN d.service_class_start_time > compile_start THEN compile_start ELSE d.service_class_start_time END,d.queue_end_time)) AS wlm_queue_time, SUM(datediff (us,d.queue_end_time,d.service_class_end_time) - compile_us) AS exec_only_time, nvl(SUM(datediff (us,CASE WHEN node > -1 THEN c.startwork ELSE c.startqueue END,c.startwork)),0) commit_queue_time, nvl(SUM(datediff (us,c.startwork,c.endtime)),0) commit_time, SUM(datediff (us,CASE WHEN d.service_class_start_time > compile_start THEN compile_start ELSE d.service_class_start_time END,d.service_class_end_time) + CASE WHEN c.endtime IS NULL THEN 0 ELSE (datediff (us,CASE WHEN node > -1 THEN c.startwork ELSE c.startqueue END,c.endtime)) END) AS wlm_start_commit_time FROM (SELECT node, b.* FROM (SELECT -1 AS node UNION SELECT node FROM stv_slices) a, stl_wlm_query b WHERE queue_end_time > '2005-01-01' AND exec_start_time > '2005-01-01') d LEFT JOIN stl_commit_stats c USING (xid,node) JOIN (SELECT query, MIN(starttime) AS compile_start, SUM(datediff (us,starttime,endtime)) AS compile_us FROM svl_compile GROUP BY 1) e USING (query) WHERE d.xid > 0 AND d.service_class > 4 AND d.final_state <> 'Evicted' GROUP BY trunc(d.service_class_start_time), d.service_class, d.node ORDER BY trunc(d.service_class_start_time), d.service_class, d.node) IQ) WHERE node < 0 ORDER BY 1,2,3;
此查询提供事务总数或 xid、运行时、排队时间和提交队列的详细信息。查看提交队列的详细信息,看看频繁提交是否在影响工作负载性能。
要查看在特定时间点运行的查询的详细信息,请运行以下查询:
select b.userid,b.query,b.service_class,b.slot_count,b.xid,d.pid,d.aborted,a.compile_start,b.service_class_start_time,b.queue_end_time,b.service_class_end_time,c.startqueue as commit_startqueue,c.startwork as commit_startwork,c.endtime as commit_endtime,a.total_compile_time_s,datediff(s,b.service_class_start_time,b.queue_end_time) as wlm_queue_time_s,datediff(s,b.queue_end_time,b.service_class_end_time) as wlm_exec_time_s,datediff(s, c.startqueue, c.startwork) commit_queue_s,datediff(s, c.startwork, c.endtime) commit_time_s,undo_time_s,numtables_undone,datediff(s,a.compile_start,nvl(c.endtime,b.service_class_end_time)) total_query_s ,substring(d.querytxt,1,50) as querytext from (select query,min(starttime) as compile_start,max(endtime) as compile_end,sum(datediff(s,starttime,endtime)) as total_compile_time_s from svl_compile group by query) a left join stl_wlm_query b using (query) left join (select * from stl_commit_stats where node=-1) c using (xid) left join stl_query d using(query) left join (select xact_id_undone as xid,datediff(s,min(undo_start_ts),max(undo_end_ts)) as undo_time_s,count(distinct table_id) numtables_undone from stl_undone group by 1) e on b.xid=e.xid WHERE '2011-12-20 13:45:00' between compile_start and service_class_end_time;
**注意:**将 2011-12-20 13:45:00 替换为要检查已排队和已完成查询的具体时间和日期。
查看您的集群节点硬件性能
如果在集群维护时段内更换了节点,则该集群可能很快就会可用。但是,在更换的节点上恢复数据可能需要一些时间。在此过程中,您的集群性能可能会下降。
要确定影响集群性能的事件,请检查您的 Amazon Redshift 集群事件。
要监控数据恢复过程,请使用 STV_UNDERREPPED_BLOCKS 表。运行以下查询来检索需要数据恢复的区块:
SELECT COUNT(1) FROM STV_UNDERREPPED_BLOCKS;
**注意:**数据恢复过程的持续时间取决于集群的工作负载。要衡量集群数据恢复过程的进度,请每隔一段时间检查区块。
要检查特定节点的运行状况,请运行以下查询将其性能与其他节点进行比较:
SELECT day , node , elapsed_time_s , sum_rows , kb , kb_s , rank() over (partition by day order by kb_s) AS rank FROM ( SELECT DATE_TRUNC('day',start_time) AS day , node , sum(elapsed_time)/1000000 AS elapsed_time_s , sum(rows) AS sum_rows , sum(bytes)/1024 AS kb , (sum(bytes)/1024)/(sum(elapsed_time)/1000000) AS "kb_s" FROM svl_query_report r , stv_slices AS s WHERE r.slice = s.slice AND elapsed_time > 1000000 GROUP BY day , node ORDER BY day , node );
示例查询输出:
day node elapsed_time_s sum_rows kb kb_s rank... 4/8/20 0 3390446 686216350489 21570133592 6362 4 4/8/20 2 3842928 729467918084 23701127411 6167 3 4/8/20 3 3178239 706508591176 22022404234 6929 7 4/8/20 5 3805884 834457007483 27278553088 7167 9 4/8/20 7 6242661 433353786914 19429840046 3112 1 4/8/20 8 3376325 761021567190 23802582380 7049 8
**注意:**前面的输出显示,节点 7 处理了 19429840046 KB 的数据,持续了 6242661 秒。这比其他节点慢得多。
sum_rows 列中的行数与 kb 列中已处理的字节数之间的比率大致相同。取决于您的硬件性能,kb\ _s 列中的行数也与 sum_rows 列中的行数大致相同。如果节点在一段时间内处理的数据较少,则表明可能存在潜在的硬件问题。要检查是否存在潜在的硬件问题,请查看节点的性能图。
相关内容
- AWS 官方已更新 2 年前
- AWS 官方已更新 2 年前
- AWS 官方已更新 1 年前
- AWS 官方已更新 2 年前