Comment résoudre les problèmes de performances de cluster ou de requête dans Amazon Redshift ?

Date de la dernière mise à jour : 11/03/2021

Les performances de requête dans mon cluster Amazon Redshift se sont dégradées.  Comment résoudre ce problème et améliorer les performances de cluster ou de requête ?

Brève description

Si vous rencontrez des problèmes de performances dans votre cluster Amazon Redshift, envisagez les approches suivantes :

  • Surveillez les métriques de performance de votre cluster.
  • Consultez les recommandations d'Amazon Redshift Advisor.
  • Examinez les alertes d'exécution de requêtes et une utilisation excessive du disque.
  • Vérifiez s'il existe des problèmes de verrouillage et des sessions longues ou des transactions à long terme.
  • Vérifiez votre configuration de gestion des charges de travail (WLM).
  • Vérifiez la maintenance et les performances matérielles de votre nœud de cluster.

Résolution

Surveiller les métriques de performance de votre cluster

Si vous constatez des problèmes de performances avec votre cluster Amazon Redshift, passez en revue les métriques et graphiques de performances de votre cluster. Les métriques et graphiques des performances du cluster peuvent vous aider à déterminer la cause racine probable de la dégradation de vos performances. Vous pouvez afficher les données de performances dans la console Amazon Redshift pour comparer les performances du cluster dans le temps.

Une augmentation de ces mesures peut indiquer une charge de travail plus importante et des conflits de ressources plus élevés sur votre cluster Amazon Redshift. Pour plus d'informations sur la surveillance des métriques de performances, consultez Surveillance d'Amazon Redshift à l'aide des métriques Amazon CloudWatch .

Vérifiez la répartition de l'exécution des charges de travail dans la console Amazon Redshift pour examiner des requêtes spécifiques et des délais d'exécution en particulier. Par exemple, si vous constatez un accroissement du délai de planification des requêtes, il peut s'agir d'une indication d'une requête en attente de verrouillage.

Consulter les recommandations d'Amazon Redshift Advisor

Amazon Redshift Advisor propose des recommandations sur la façon d'améliorer et d'optimiser les performances de votre cluster Amazon Redshift. Amazon Redshift Advisor est disponible gratuitement dans la console Amazon Redshift. Utilisez les recommandations Amazon Redshift Advisor pour en savoir plus sur les domaines d'amélioration potentiels de votre cluster. Les recommandations sont basées sur des schémas courants d'utilisation et sur les meilleures pratiques d'Amazon Redshift.

Examiner les alertes d'exécution de requêtes et une utilisation excessive du disque

Lors de l'exécution d'une requête, Amazon Redshift note les performances de la requête et indique si la requête s'exécute efficacement. Si la requête est identifiée comme inefficace, Amazon Redshift note l'ID de requête et fournit des recommandations pour améliorer les performances de la requête. Ces recommandations sont journalisées dans STL_ALERT_EVENT_LOG, un tableau système interne.

Si vous observez une requête lente ou inefficace, vérifiez les entrées du journal STL_ALERT_EVENT_LOG. Pour récupérer des informations à partir de STL_ALERT_EVENT_LOG, utilisez la requête suivante :

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;

Cette requête répertorie les ID de requêtes ainsi que les problèmes les plus courants et les occurrences de problème pour la requête exécutée sur le cluster.

Voici un exemple de sortie de la requête et les informations décrivant la raison pour laquelle votre alerte a été déclenchée :

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

Vérifiez les performances des requêtes en cochant la case requêtes de diagnostic pour le réglage des requêtes. Assurez-vous que vos opérations de requêtes sont conçues pour s'exécuter efficacement. Par exemple, toutes les opérations de jonction ne sont pas efficaces. Une jonction par boucles imbriquées est le type de jonction le moins efficace et elle doit être évitée autant que possible car ce type augmente considérablement le délai d'exécution de la requête.

Identifiez les requêtes exécutant des boucles imbriquées pour vous aider à détecter le problème. Pour plus d'informations sur la façon de détecter les problèmes courants d'utilisation du disque, consultez Comment résoudre un problème d'utilisation élevée ou complète du disque avec Amazon Redshift ?

Rechercher les problèmes de verrouillage et les sessions longues ou les transactions à long terme

Avant qu'une requête ne soit exécutée sur le cluster, des verrous au niveau de la table peuvent être nécessaires sur les tables impliquées dans l'exécution de la requête. Dans certains cas, les requêtes peuvent apparaître comme « suspendues », ou un pic peut survenir dans le délai d'exécution de la requête. Si vous observez un pic dans le délai d'exécution de votre requête, un problème de verrouillage peut en être la cause. Pour plus d'informations sur les retards de délai d'exécution de requête, consultez Pourquoi le délai de planification de ma requête est-il si élevé dans Amazon Redshift ?

Si votre tableau est actuellement verrouillé par un autre processus ou une autre requête, votre requête ne peut pas s'exécuter. Par conséquent, votre requête n'apparaîtra pas dans le tableau STV_INFLIGHT. Au lieu de cela, votre requête en cours d'exécution apparaîtra dans le tableau STV_RECENTS.

Parfois, une requête peut se retrouver bloquée à cause d'une transaction à long terme. Pour éviter que des transactions à long terme n'impactent les performances de votre requête, suivez les conseils suivants :

  • Identifiez les sessions longue durée et arrêtez-les immédiatement. Vous pouvez utiliser les tableaux STL_SESSIONS et SVV_TRANSACTIONS pour vérifier les transactions à long terme.
  • Concevez vos requêtes de telle sorte qu'Amazon Redshift puisse les traiter rapidement et efficacement.

Remarque : Les transactions à long terme affectent également la capacité de VACUUM à récupérer de l'espace disque, ce qui augmente le nombre de lignes fantômes ou lignes non validées. Les lignes fantômes qui sont analysées par les requêtes peuvent affecter les performances de ces requêtes.

Pour plus d'informations sur l'identification des sessions longue durée qui risquent de verrouiller des tableaux, consultez Comment détecter et désactiver des verrous dans Amazon Redshift ?

Vérifier votre configuration de gestion des charges de travail (WLM)

En fonction de votre configuration WLM, une requête peut immédiatement commencer à s'exécuter ou passer du temps en file d'attente. L'objectif doit toujours être de minimiser la durée de file d'attente d'une requête avant son exécution. Si vous souhaitez définir vos files d'attente, consultez votre allocation de mémoire WLM.

Pour vérifier les files d'attente WLM d'un cluster sur plusieurs jours, utilisez la requête suivante :

SELECT *, pct_compile_time + pct_wlm_queue_time + pct_exec_only_time + pct_commit_queue_time + pct_commit_time AS total_pcnt
FROM 
(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;

Cette requête affiche le nombre total de transactions (xid), les délais d'exécution, l'heure de mise en file d'attente et les détails de la file d'attente de validation. Vous pouvez consulter les détails de la file d'attente de validation pour voir si les validations fréquentes ont un impact sur les performances de la charge de travail.

Pour vérifier les détails des requêtes exécutées à un moment donné, utilisez la requête suivante :

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;

Remplacez « 2011-12-20 13:45:00 » par l'heure et la date exactes auxquelles vous souhaitez vérifier les requêtes en file d'attente et terminées.

Vérifier les performances matérielles de votre nœud de cluster

Durant votre fenêtre de maintenance de cluster, des tâches de maintenance telles que l'application de correctifs, les modifications de configuration interne et le remplacement des nœuds peuvent avoir lieu. Si un nœud a été remplacé pendant la fenêtre de maintenance, le cluster peut être disponible prochainement. Toutefois, la restauration des données sur le nœud remplacé peut prendre un certain temps. Ce processus est connu sous le nom d'hydratation. Pendant le processus d'hydratation, les performances de votre cluster peuvent diminuer.

Pour identifier les événements (tels que l'hydratation) qui ont influencé les performances de votre cluster, vérifiez vos événements de cluster Amazon Redshift. Vos événements de cluster vous informent de toute action de remplacement de nœud ou de toutes autres actions de cluster qui sont exécutées.

Pour surveiller le processus d'hydratation, utilisez le tableau STV_UNDERREPPED_BLOCKS. Les blocs nécessitant une hydratation peuvent être récupérés à l'aide de la requête suivante :

SELECT COUNT(1) FROM STV_UNDERREPPED_BLOCKS;

Remarque : La durée du processus d'hydratation dépend de la charge de travail du cluster. Pour mesurer la progression du processus d'hydratation de votre cluster, vérifiez les blocs à intervalles donnés.

Pour vérifier l'intégrité d'un nœud en particulier, utilisez la requête suivante pour comparer ses performances à celles d'autres nœuds :

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
);

Voici un exemple de sortie de requête :

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
...This output indicates that the node 7 processed 19429840046 Kb of data for 6242661 amount of seconds, which is a lot slower than the other nodes.

Le rapport entre le nombre de lignes (colonne « sum_rows ») et le nombre d'octets traités (colonne « kb ») est à peu près le même. Le nombre de lignes dans la colonne « kb_s » est également à peu près le même que le nombre de lignes, sous réserve des performances de votre matériel. Si vous constatez qu'un nœud en particulier traite moins de données sur une période spécifique, cette faible performance peut révéler un problème matériel sous-jacent. Pour confirmer qu'il existe un problème matériel sous-jacent, consultez le graphique des performances du nœud.


Cet article vous a-t-il été utile ?


Besoin d'aide pour une question technique ou de facturation ?