如何解决 Amazon Redshift 中的集群或查询性能问题?

4 分钟阅读
0

我想解决我的 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_SESSIONSSVV_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 官方
AWS 官方已更新 1 年前