PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Jak w prosty i efektywny sposób wyszukiwać zagnieżdżone relacje w SQL?

Jak w przypadku każdego zapytania, najbardziej wydajną metodą jest „to zależy”. W grę wchodzi wiele zmiennych - liczba wierszy w tabelach, długość wierszy, istnienie indeksów, pamięć RAM na serwerze itp.

Najlepszym sposobem, w jaki mogę sobie wyobrazić rozwiązanie tego rodzaju problemu (myśląc o łatwości utrzymania i dobrym podejściu do wydajności), jest użycie CTE, które pozwala na utworzenie tymczasowego wyniku i ponowne wykorzystanie go w całym zapytaniu. CTE używają słowa kluczowego WITH i zasadniczo aliasują wynik jako tabelę, dzięki czemu można wielokrotnie JOIN przeciwko niemu:

WITH user_memberships AS (
    SELECT *
    FROM memberships
    WHERE user_id = ${id}
), user_apps AS (
    SELECT *
    FROM apps
    INNER JOIN user_memberships
        ON user_memberships.team_id = apps.team_id
), user_collections AS (
    SELECT *
    FROM collections
    INNER JOIN user_memberships
        ON user_memberships.team_id = collections.team_id
), user_webhooks AS (
    SELECT *
    FROM webhooks
    LEFT OUTER JOIN user_collections ON user_collections.id = webhooks.collection_id
    INNER JOIN user_memberships
        ON user_memberships.team_id = webhooks.team_id
        OR user_memberships.team_id = user_collections.team_id
)

SELECT events.* 
FROM events
WHERE app_id IN (SELECT id FROM user_apps)
OR collection_id IN (SELECT id FROM user_collections)
OR membership_id IN (SELECT id FROM user_memberships)
OR team_id IN (SELECT team_id FROM user_memberships)
OR user_id = ${id}
OR webhook_id IN (SELECT id FROM user_webhooks)
;

Korzyści płynące z robienia tego w ten sposób to:

  1. Każde CTE może skorzystać z indeksu na odpowiednich predykatach JOIN i szybciej zwrócić wyniki tylko dla tego podzbioru, zamiast zmuszać planistę wykonania do próby rozwiązania serii złożonych predykatów
  2. CTE mogą być utrzymywane indywidualnie, co ułatwia rozwiązywanie problemów z podzbiorami
  3. Nie naruszasz zasady DRY
  4. Jeśli CTE ma wartość poza zapytaniem, możesz przenieść ją do procedury składowanej i odwołać się do niej


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak podzielić imię na nazwisko i inicjały?

  2. Odpowiednie wartości dla -Infinity &Infinity w Postgres

  3. Rozplątanie aktualizacji PostgreSQL

  4. Błąd typu instrukcji zagnieżdżonej sprawy (postgres)

  5. PostgreSQL Zapisz i wybierz pliki przy użyciu danych binarnych Bytea z C libpq