Temat: Join i wolne sortowanie
Witam,
Dla uproszczenia mam dwie tabele (offers - oferty czyli opiso wycieczek/hoteli, termins - lista terminów do oferty):
CREATE TABLE "offers"(
"offerId" SERIAL PRIMARY KEY,
"name" varchar(128) NOT NULL,
...);
CREATE TABLE "termins"(
"terminId" SERIAL PRIMARY KEY,
"offerId" int NOT NULL REFERENCES "offers" ON DELETE CASCADE ON UPDATE CASCADE,
"dateFrom" date NOT NULL,
"price" numeric NOT NULL,
...);
Wykonujemy następujące zapytanie, którego celem jest wyszukanie ofert z najlepszym terminem spełniającym warunki.
SELECT
*
FROM
(
SELECT
DISTINCT ON("offerId") te."terminId", te."dateFrom", te."price", te."offerId"
FROM
termins te
WHERE
"dateFrom" > now()
ORDER BY
"offerId", "price"
) t
INNER JOIN
"offers" o ON(o."offerId" = t."offerId")
LIMIT 10
Limit (cost=0.00..42.10 rows=10 width=187)
-> Merge Left Join (cost=0.00..10348.97 rows=2458 width=187)
Merge Cond: (te."offerId" = o."offerId")
-> Unique (cost=0.00..9002.22 rows=2458 width=44)
-> Index Scan using "offerId_price_idx" on termins te (cost=0.00..8722.18 rows=112013 width=44)
Filter: ("dateFrom" > now())
-> Index Scan using offers_pkey on offers o (cost=0.00..1274.61 rows=6735 width=143)
Teraz dodajemy sortowanie po kolumnie "price":
SELECT
*
FROM
(
SELECT
DISTINCT ON("offerId") te."terminId", te."dateFrom", te."price", te."offerId"
FROM
termins te
WHERE
"dateFrom" > now()
ORDER BY
"offerId", "price"
) t
INNER JOIN
"offers" o ON(o."offerId" = t."offerId")
ORDER BY
"price"
LIMIT 10
Limit (cost=9863.39..9863.42 rows=10 width=187)
-> Sort (cost=9863.39..9869.54 rows=2458 width=187)
Sort Key: te.price
-> Hash Left Join (cost=562.54..9810.27 rows=2458 width=187)
Hash Cond: (te."offerId" = o."offerId")
-> Unique (cost=0.00..9002.21 rows=2458 width=44)
-> Index Scan using "offerId_price_idx" on termins te (cost=0.00..8722.18 rows=112012 width=44)
Filter: ("dateFrom" > now())
-> Hash (cost=339.35..339.35 rows=6735 width=143)
-> Seq Scan on offers o (cost=0.00..339.35 rows=6735 width=143)
Czas wykonania zapytania zwiększa się około 10 na lokalnym komputerze (110 000 terminów i 6700 ofert).
Czas wykonania zapytania na serwerze do docelowym zwiększa się około 200 razy (310 000 terminów - docelowo 1 000 000, 12 000 ofert docelowo - 20 000).
Zapytanie na serwerze docelowym trwa już około 1-1.5 sekundy, a do tego jeszcze dojdą left joiny do 5-6 tabel zawierających nazwę miasta, kraju, typ zakwaterowania.. ale to nie ma tutaj znaczenia.
Czy jest szansa, aby to zapytanie trwało krócej? Zastanawiam się czy jakieś indeksy można tutaj potworzyć np. by hash left join przyspieszyć?
Mam założony indeks na "price" oraz wspólny na "offerId" i "price". Nie mam założonego indeksu na klucz obcy "offerId".