2017-07-20 4 views
0

je un (très grand) table comme ceTraitement des fonctions OLAP - Pourquoi est-il plus rapide de fonctionner sur des partitions N/M M fois que les enregistrements N 1 fois

CREATE SET TABLE LOAN 
    (LoanNumber VARCHAR(100), 
    LoanBalance DECIMAL(18,4), 
    RecTimeStamp TIMESTAMP(0) 
) 
PRIMARY INDEX (LoanNumber) 
PARTITION BY RANGE_N 
    (ROW_INS_TS BETWEEN 
     TIMESTAMP '2017-01-01 00:00:00+00:00' 
    AND TIMESTAMP '2017-12-31 23:59:59+00:00' 
    EACH INTERVAL '1' DAY 
); 

Ce tableau obtient généralement enroulé par les instantanés , par exemple, l'instantané de fin de mois d'avril serait

-- Pretend there is just 2017 data there 
CREATE SET TABLE LOAN_APRIL AS 
    (SELECT * 
     FROM LOAN 
    WHERE RecTimeStamp <= DATE '2017-04-30' 
    QUALIFY row_number() OVER 
      (PARTITION BY LoanNumber 
        ORDER BY RecTimeStamp DESC 
      ) = 1 
) 
PRIMARY INDEX (LoanNumber); 

Ce qui prend généralement assez de temps à s'exécuter. J'expérimentais hier bien et trouvé que j'avais très bon temps d'exécution en la décomposant comme celui-ci

CREATE SET TABLE LOAN_APRIL_TMP 
    (LoanNumber VARCHAR(100), 
    LoanBalance DECIMAL(18,4), 
    RecTimeStamp TIMESTAMP(0) 
) 
PRIMARY INDEX (LoanNumber); 

CREATE SET TABLE LOAN_APRIL 
    (LoanNumber VARCHAR(100), 
    LoanBalance DECIMAL(18,4), 
    RecTimeStamp TIMESTAMP(0) 
) 
PRIMARY INDEX (LoanNumber); 

INSERT INTO LOAN_APRIL_TMP 
    SELECT * 
     FROM LOAN 
    WHERE RecTimeStamp BETWEEN DATE '2017-01-01' AND DATE '2017-01-31' 
    QUALIFY row_number() OVER 
      (PARTITION BY LoanNumber 
        ORDER BY RecTimeStamp DESC 
      ) = 1; 

INSERT INTO LOAN_APRIL_TMP 
    SELECT * 
     FROM LOAN 
    WHERE RecTimeStamp BETWEEN DATE '2017-02-01' AND DATE '2017-02-28' 
    QUALIFY row_number() OVER 
      (PARTITION BY LoanNumber 
        ORDER BY RecTimeStamp DESC 
      ) = 1; 

INSERT INTO LOAN_APRIL_TMP 
    SELECT * 
     FROM LOAN 
    WHERE RecTimeStamp BETWEEN DATE '2017-03-01' AND DATE '2017-03-31' 
    QUALIFY row_number() OVER 
      (PARTITION BY LoanNumber 
        ORDER BY RecTimeStamp DESC 
      ) = 1; 

INSERT INTO LOAN_APRIL_TMP 
    SELECT * 
     FROM LOAN 
    WHERE RecTimeStamp BETWEEN DATE '2017-04-01' AND DATE '2017-04-30' 
    QUALIFY row_number() OVER 
      (PARTITION BY LoanNumber 
        ORDER BY RecTimeStamp DESC 
      ) = 1; 

INSERT INTO LOAN_APRIL 
    SELECT * 
     FROM LOAN_APRIL_TMP 
    QUALIFY row_number() OVER 
      (PARTITION BY LoanNumber 
        ORDER BY RecTimeStamp DESC 
      ) = 1; 

Je viens de rencontrer cette séquence, de sorte qu'ils n'exécuta en parallèle. Aujourd'hui, je vais expérimenter pour voir chaque segment à charger en parallèle.

De plus, à un point plus important, j'ai de la difficulté à trouver une documentation suffisamment technique pour comprendre ces types de questions. Y a-t-il une bonne ressource pour cela? Je comprends qu'il y a beaucoup de problèmes de propriété, mais il doit y avoir quelque chose qui décrit, au moins à un niveau élevé, la mise en œuvre de ces fonctions.

Répondre

2

Il peut y avoir plusieurs raisons. Vous devriez vérifier DBQL pour voir les différences réelles d'utilisation des ressources. Les données du 1er Select sont réparties sur plus de partitions que les plus petites sélections. Explication peut montrer spool ne sera pas chached dans la mémoire pour le grand Select, mais pas pour les séparés.

  • Varchars à order by sont développés à Chars de la taille définie, si LoanNumber est en fait un VarChar(100) (je doute que ce soit), il augmentera la bobine aussi (mais cela est un problème commun pour d'autres requêtes sur cette table). Il existe un inconvénient des fonctions OLAP, elles ont besoin de deux bobines, à savoir le double de la taille de la bobine. Si cette table a beaucoup de colonnes/grandes lignes, il pourrait être beaucoup plus efficace pour exécuter le ROW_NUMBER seulement contre la pharmacocinétique de la table, puis rejoindre en arrière comme ceci:

    CREATE SET TABLE LOAN_APRIL_TMP 
        (LoanNumber VARCHAR(100), 
        RecTimeStamp TIMESTAMP(0) 
    ) 
    PRIMARY INDEX (LoanNumber) -- same PPI as source table to facilitate fast join back 
    PARTITION BY RANGE_N 
        (ROW_INS_TS BETWEEN 
         TIMESTAMP '2017-01-01 00:00:00+00:00' 
        AND TIMESTAMP '2017-12-31 23:59:59+00:00' 
        EACH INTERVAL '1' DAY 
    ); 
    
    INSERT INTO LOAN_APRIL_TMP 
    SELECT LoanNumber, RecTimeStamp -- no other columns 
    FROM LOAN 
    WHERE RecTimeStamp <= DATE '2017-04-30' 
    QUALIFY row_number() OVER 
          (PARTITION BY LoanNumber 
            ORDER BY RecTimeStamp DESC 
          ) = 1 
    ; 
    
    INSERT INTO LOAN_APRIL 
    SELECT l.* -- now get all columns 
    FROM LOAN AS l 
    JOIN LOAN_APRIL_TMP AS AS tmp 
        ON l.LoanNumber = tmp.LoanNumber 
    AND l.RecTimeStamp = tmp.RecTimeStamp 
    
  • +0

    @YellowBedwetter: Pouvez-vous s'il vous plaît ajouter quelques informations après tester si cela a effectivement amélioré les performances? – dnoeth