Selectiv Predicat Pushdown Pentru A Vizualiza

0

Problema

Am o mare coloana magazin de masă, care devine actualizări frecvente. Nu ingera actualizări direct în sursa de masă, pentru că ar provoca, în cele mai multe cazuri, un număr mic de actualizări pentru a provoca o masă plină micro partiție reconstrui. În schimb am actualizări de flux de la un update de masă, și la interogare timp am combina pe ambele. În practică, acest lucru funcționează bine.

Deci simplifica lucrurile, voi arunca acest lucru într-o vizualizare 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
)

Ambele users masă și user_changes tabel au aceeași schemă precum și unele partitii configurare. În acest fel pot folosi predicatul pushdown pe view pentru a selecta doar utilizatorii în partiția corectă. Să zicem că acesta este account_id.

SELECT * FROM users_view
WHERE account_id = 1234

Dar users masa este destul de un pic mai mare decât user_changes masă, și aș vrea să împingă și mai predicate la users masă fără împingând suplimentare predicate la user_changes masă. De ce? Pentru potrivire pe users masă, în timp ce 98% corecte, are rezultate fals pozitive/negative. Detalii de user_changes sunt necesare pentru a stabili drepte record. Ceea ce ar arata ca in afara de un punct de vedere este acesta:

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'

Cât de rău arată, e mult mai performant. Toate condițiile pot fi aplicate mult mai mare users masă, dar numai neschimbătoare condiții pot fi aplicate la users_changes masă. de exemplu, Un utilizator poate schimba orașe, dar un utilizator nu poate modifica conturi. Cel de-al doilea fugi de toate condițiile, după uniunii este de a prinde orice modificări user_changes a introdus.

Acest lucru este dificil de a scrie, și chiar mai mult ca interogarea devine complicat și de interogare constructori implicați. Deci, eu sunt în căutarea pentru o modalitate mod de a convinge sql planner pentru a sări peste predicat pushdown de unele predicate pe user_changes tabelul fără a fi nevoie să formatați interogare de genul asta. În mod ideal, cu o vedere.

PSEUDO SQL. PSEUDO SQL. PSEUDO SQL

În visele mele am putea spune interogare planificator unde se poate folosi partition predicate, și în cazul în care se poate folosi non-partiție predicate.

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'

Orice idei nebunești?

1

Cel mai bun răspuns

1

puteți adăuga suplimentar coloana src pentru determinarea sursei de masă și înfășurați predicate în CAZUL:

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

Foarte tare ideea! Vă mulțumesc!
micah

@micah puteți încheia toate predicatele într-un singur CAZ, folosind ȘI sau SAU: then city = 'Chicago' AND one_more_condition AND some_other_condition
leftjoin

În alte limbi

Această pagină este în alte limbi

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