Selettiva Predicato Pushdown Per Visualizzare

0

Domanda

Ho una grande colonna di tabella di archivio che viene frequenti aggiornamenti. Io non ingerire gli aggiornamenti direttamente nella tabella di origine, poiché potrebbe causare, nella maggior parte dei casi, un piccolo numero di aggiornamenti a causa di un tavolo pieno di micro partizione di ricostruzione. Io invece flusso di aggiornamenti per un aggiornamento della tabella, e al momento della query mi combinano entrambi. In pratica questo funziona bene.

Così semplificare le cose, io lancio questo in vista users_view.

CREATE OR REPLACE VIEW users_view AS (
    SELECT * FROM users
    UNION ALL 
    SELECT * FROM user_changes
    QUALIFY ROW_NUMBER() OVER(
        PARTITION BY id 
        ORDER BY last_updated_at DESC
    ) = 1
)

Sia il users tabella e user_changes tabella hanno lo stesso schema e la configurazione della partizione. In questo modo posso usare il predicato pushdown sulla vista per selezionare solo gli utenti all'interno della partizione corretta. Diciamo che questa è la account_id.

SELECT * FROM users_view
WHERE account_id = 1234

Ma il users la tabella è un po ' più grande rispetto alla user_changes tabella, e mi piacerebbe spingere ancora di più predicati giù per la users tabella senza spingere ulteriori predicati giù per la user_changes tabella. Perché? Perché matching su users tabella, mentre il 98% di precisione, dispone di falsi positivi/negativi. I dettagli user_changes sono necessari per impostare il record dritto. Come sarà l'aspetto esterno di una vista è questo:

SELECT * FROM (
    SELECT * FROM users
    WHERE account_id = 1234 AND city = 'Chicago'
    UNION ALL 
    SELECT * FROM user_changes
    WHERE account_id = 1234
    QUALIFY ROW_NUMBER() OVER(
        PARTITION BY id 
        ORDER BY last_updated_at DESC
    ) = 1
)
WHERE account_id = 1234 AND city = 'Chicago'

Come brutto come questo sembra, è molto più performante. Tutte le condizioni possono essere applicate per il più grande users tabella, ma solo immutabili condizioni possono essere applicate per la users_changes tabella. cioè Un utente può cambiare la città, ma un utente non può modificare gli account. La seconda esecuzione di tutte le condizioni dopo l'unione per la cattura di eventuali modifiche l' user_changes introdotto.

Questo è complicato da scrivere, e ancor di più come la query diventa complicato e di query costruttori coinvolti. Quindi sto cercando un modo per convincere sql planner per saltare predicato pushdown di alcuni predicati sul mio user_changes tabella senza bisogno di formattare la query come questa. Idealmente con vista.

PSUEDO SQL. PSUEDO SQL. PSUEDO SQL

Nei miei sogni posso dire che la query planner dove è possibile utilizzare la partizione di predicati, e dove è possibile utilizzare la partizione non di predicati.

CREATE OR REPLACE VIEW users_view AS (
    SELECT * FROM (
        SELECT * FROM users
        %PARTITION_PREDICATES%
        %NON_PARTITION_PREDICATES%

        UNION ALL 

        SELECT * FROM user_changes
        %PARTITION_PREDICATES%

        QUALIFY ROW_NUMBER() OVER(
            PARTITION BY id 
            ORDER BY last_updated_at DESC
        ) = 1
    )
    %PARTITION_PREDICATES%
    %NON_PARTITION_PREDICATES%
)

SELECT * FROM users_view
WHERE account_id = 1234 AND city = 'Chicago'

Eventuali idee folli?

1

Migliore risposta

1

è possibile aggiungere ulteriori colonne src per determinare la tabella di origine e avvolgere predicati nel CASO:

select * from
(
SELECT u.*, 'users' as src FROM users u
union all
SELECT uc.*, 'users_changes' as src FROM users_changes uc
) 
WHERE --applied only to users
      case when src  = 'users' 
                 then city = 'Chicago' --predicate wrapped in case
           else true
       end
  --applied to all
  AND account=12345 
2021-11-23 14:58:40

Idea molto interessante! Grazie!
micah

@mica si può avvolgere tutti i predicati nel singolo CASO l'utilizzo E o O: then city = 'Chicago' AND one_more_condition AND some_other_condition
leftjoin

In altre lingue

Questa pagina è in altre lingue

Русский
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................