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

Jak napisać sprzężenie z tymi nietypowymi kryteriami dopasowania?

Indeksy

Twórz indeksy na x.id i y.id - które prawdopodobnie już masz, jeśli są to twoje klucze podstawowe.
Indeks wielokolumnowy też może pomóc, szczególnie z skanowania tylko do indeksowania na stronie 9.2+:

CREATE INDEX y_mult_idx ON y (id DESC, val)

Jednak w moich testach ten wskaźnik nie był początkowo używany. Musiałem dodać (inaczej bez sensu) val do ORDER BY aby przekonać planistę zapytań, że kolejność sortowania jest zgodna. Zobacz zapytanie 3 .

Indeks nie ma większego znaczenia w tej syntetycznej konfiguracji. Ale w przypadku tabel z większą liczbą kolumn pobieranie val z tabeli staje się coraz droższy, dzięki czemu indeks „pokrywania” staje się bardziej atrakcyjny.

Zapytania

1) Prosty

SELECT DISTINCT ON (x.id)
       x.id, y.val
FROM   x
JOIN   y ON y.id <= x.id
ORDER  BY x.id, y.id DESC;

Skrzypce SQL.

Więcej wyjaśnień techniki z DISTINCT w tej powiązanej odpowiedzi:

Przeprowadziłem kilka testów, ponieważ miałem podejrzenia, że ​​pierwsze zapytanie nie będzie się dobrze skalować. Jest szybki przy małym stole, ale nie jest dobry przy większych stołach. Postgres nie optymalizuje planu i zaczyna od (ograniczonego) połączenia krzyżowego, którego koszt to O(N²) .

2) Szybko

To zapytanie jest nadal dość proste i doskonale skaluje się:

SELECT x.id, y.val
FROM   x
JOIN  (SELECT *, lead(id, 1, 2147483647) OVER (ORDER BY id) AS next_id FROM y) y
       ON  x.id >= y.id
       AND x.id <  y.next_id
ORDER  BY 1;

Funkcja okna lead() jest instrumentalny. Korzystam z opcji, aby zapewnić domyślną osłonę narożnej wielkości ostatniego wiersza:2147483647 to największa możliwa liczba całkowita . Dostosuj się do swojego typu danych.

3) Bardzo proste i prawie tak samo szybkie

SELECT x.id
     ,(SELECT val FROM y WHERE id <= x.id ORDER BY id DESC, val LIMIT 1) AS val
FROM   x;

Zwykle skorelowane podzapytania są powolne. Ale ten może po prostu wybrać wartość z indeksu (pokrywającego), a poza tym jest tak prosty, że może konkurować.

Dodatkowe ORDER BY element val (wytłuszczone podkreślenie) wydaje się bezcelowe. Jednak dodanie go przekonuje planistę zapytań, że można użyć indeksu wielokolumnowego y_mult_idx z góry, ponieważ kolejność sortowania jest zgodna. Zwróć uwagę na

w EXPLAIN wyjście.

Przypadek testowy

Po ożywionej debacie i wielu aktualizacjach zebrałem wszystkie wysłane do tej pory zapytania i stworzyłem przypadek testowy do szybkiego przeglądu. Używam tylko 1000 wierszy, więc SQLfiddle nie przekracza limitu czasu przy wolniejszych zapytaniach. Ale top 4 (Erwin 2, Clodoaldo, a_horse, Erwin 3) skaluje się liniowo we wszystkich moich lokalnych testach. Zaktualizowano jeszcze raz, aby uwzględnić mój najnowszy dodatek, poprawić format i kolejność według wydajności:

Wielkie skrzypce SQL porównywanie wydajności.



  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 obliczyć czas pomiędzy dwoma znacznikami czasu (PostgreSQL)

  2. Wykryj zduplikowane elementy w rekurencyjnym CTE

  3. Nie można znaleźć punktu wejścia o nazwie „InterlockedIncrement” w bibliotece DLL „kernel32.dll” — [ochrona poczty e-mail] 64-bitowa

  4. Postgres SQL SELECT i UPDATE zachowują się inaczej

  5. Jak Sin() działa w PostgreSQL