Skocz do zawartości
januzi

potrzebna pomoc przy indeksach w postgresie

Rekomendowane odpowiedzi

czy ktoś zna na tyle postgresa, że mógłby podpowiedzieć jaki indeks dołożyć do zapytania:

 

SELECT
           way, surface,
           COALESCE(CASE WHEN landuse = 'forest' THEN 'wood' ELSE NULL END, "natural") AS "natural",
           CASE WHEN "natural" = 'mud'
               THEN "natural"
               ELSE CASE WHEN ("natural" = 'wetland' AND NOT tags ? 'wetland')
                 THEN 'wetland'
                 ELSE CASE WHEN ("natural" = 'wetland')
                   THEN tags->'wetland'
                   ELSE NULL
                   END
               END
             END AS int_wetland,
           tags->'leaf_type' AS leaf_type,
           way_area/NULLIF(POW(545979*0.001*0.28,2),0) AS way_pixels
         FROM planet_osm_polygon
         WHERE ("natural" IN ('mud', 'wetland', 'wood', 'beach', 'shoal', 'reef', 'scrub', 'sand') OR landuse = 'forest')
           AND building IS NULL
           AND way_area > 1*152.874::real*152.874::real
         ORDER BY COALESCE(layer,0), way_area DESC

żeby wykonywało się ono szybciej i żeby explain analyze nie zwracało wyników typu:

Sort  (cost=813535.97..813553.26 rows=6915 width=318) (actual time=208780.325..211611.095 rows=302446 loops=1)
  Sort Key: (COALESCE(layer, 0)), way_area DESC
  Sort Method: external merge  Disk: 221952kB
  ->  Seq Scan on planet_osm_polygon  (cost=0.00..813094.95 rows=6915 width=318) (actual time=65.277..197295.161 rows=302446 loops=1)
        Filter: ((building IS NULL) AND (way_area > '23370.4577112803'::double precision) AND (("natural" = ANY ('{mud,wetland,wood,beach,shoal,reef,scrub,sand}'::text[])) OR (landuse = 'forest'::text)))
        Rows Removed by Filter: 13136953
Planning time: 590.256 ms
Execution time: 211884.360 ms
(8 rows)

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Wg mnie to zapytanie jest problemem samo w sobie. To:

 

COALESCE(CASE WHEN landuse = 'forest' THEN 'wood' ELSE NULL END, "natural") AS "natural"

buduje kolumnę natural, która może mieć dwie wartości: 'wood', gdy kolumna landuse ma wartość 'forest', albo 'natural' w przeciwnym razie. Po co więc ten IN w WHERE? Samo landuse = 'forest' da to samo, bo wiadomo, że IN(..., 'wood', ...) będzie spełniony. Wtedy landuse jest dobrym kandydatem na index.

Podobna uwaga do CASE WHEN "natural" = 'mud'. Po co, skoro to nigdy się nie spełni?

Nie kumam też rzutowania i mnożenia w WHERE. Nie można od razu przyrównać do żądanej wartości?

 

Pozostałe kolumny w tabeli to loteria w indeksowaniu, zależnie od danych w tabeli. IS NULL na building ma szanse skorzystać z indexu, jeśli tych NULLi jest odsetek wszystkich wartości. Podobnie z warunkiem większości na way_area. Jeśli odfiltrowuje on jakieś 95% wszystkich wartości, to index ma sens. W przeciwnym razie, jego użycie może być kosztowniejsze od full scana.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Takie coś jest w domyślnych stylach dla open street mapa. To zewnętrze way_area jest chyba liczone na żywca, dlatego jest wstawiane w taki sposób:

AND way_area > 0.01*!pixel_width!::real*!pixel_height!::real

 

W innych miejscach jest dużo gorzej, np. zapytanie ma pięć ekranów (widok konsolowy, po połączeniu przez ssh), w którym jest 5 selectów w unionie, z where typu:

FROM planet_osm_line
             WHERE (tunnel IS NULL OR NOT tunnel IN ('yes', 'building_passage'))
               AND (covered IS NULL OR NOT covered = 'yes')
               AND (bridge IS NULL OR NOT bridge IN ('yes', 'boardwalk', 'cantilever', 'covered', 'low_water_crossing', 'movable', 'trestle', 'viaduct'))
               AND highway IS NOT NULL -- end of road select

 

Tutaj za cholerę nie da się chyba wrzucić indeksów (dałem na highway, ale nie pomogło).

 

Może pomóc trochę systemowi i dorzucić własne kolumny, które będą zawierać tylko to co potrzeba? Jak w tym where powyżej? Coś na zasadzie: moja_kolumna (boolean, tinyint, o ile takie są w postgresie?) i potem update set moja_kolumna = 1 where ( ). Na koniec indeks na to i w samym zapytaniu zmienić where na moja_kolumna = 1.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Nie ma definicji aliasu way_area w zapytaniu, więc IMO jest to kolumna.

 

Nie kumam, jak chcesz dodać kolumny do istniejących tabel. Przecież tam są już jakieś dane i jeśli coś je zmieni, to Twoje nowe kolumny się same nie zaktualizują. Jak chcesz iść w tym kierunku, to próbowałbym stworzyć widok z tymi danymi, co potrzebujesz, a oryginalne tabele zaindeksował. Widok będzie SELECTował oryginalne tabele i wykorzystywał ich indexy (wg uznania query plannera). Ale to nie będzie szybsze od SELECTa korzystającego z tych indexów. Więc wracasz do punktu wyjścia - grzebanie w tych SQLach. Chyba, że będzie to widok zmaterializowany. Je chyba można indexować, ale nie wiem, jak one działają.

Edytowane przez Karister

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Raczej aktualizacji nie będzie. To co siedzi będzie tylko czytane. Więc dodatkowe kolumny w niczym nie będą przeszkadzać, a mogą tylko pomóc w wyciąganiu danych.

 

 

I jeszcze jedno:

SELECT DISTINCT ON (p.way)	
           p.way AS way, l.highway AS int_tc_type,
           CASE WHEN l.service IN ('parking_aisle', 'drive-through', 'driveway')
             THEN 'INT-minor'::text
             ELSE 'INT-normal'::text
           END AS int_tc_service
         FROM planet_osm_point p
           JOIN planet_osm_line l
             ON ST_DWithin(p.way, l.way, 0.1) -- Assumes Mercator
           JOIN (VALUES
             ('tertiary', 1),
             ('unclassified', 2),
             ('residential', 3),
             ('living_street', 4),
             ('service', 5),
             ('track', 6)
             ) AS v (highway, prio)
             ON v.highway=l.highway
         WHERE p.highway = 'turning_circle'
           OR p.highway = 'turning_loop'
         ORDER BY p.way, v.prio

 

Dla tego zapytania explain pokazuje:

 

Unique  (cost=677573.21..677587.30 rows=2819 width=76)
  ->  Sort  (cost=677573.21..677580.26 rows=2819 width=76)
        Sort Key: p.way, "*VALUES*".column2
        ->  Nested Loop  (cost=0.36..677411.67 rows=2819 width=76)
              ->  Hash Join  (cost=0.15..232445.42 rows=677063 width=274)
                    Hash Cond: (l.highway = "*VALUES*".column1)
                    ->  Seq Scan on planet_osm_line l  (cost=0.00..209587.65 rows=4289865 width=270)
                    ->  Hash  (cost=0.08..0.08 rows=6 width=36)
                          ->  Values Scan on "*VALUES*"  (cost=0.00..0.08 rows=6 width=36)
              ->  Index Scan using idx_highway_c_l on planet_osm_point p  (cost=0.21..0.65 rows=1 width=32)
                    Index Cond: (way && st_expand(l.way, '0.1'::double precision))
                    Filter: ((l.way && st_expand(way, '0.1'::double precision)) AND _st_dwithin(way, l.way, '0.1'::double precision))
(12 wierszy)

 

Dobrze rozumiem, że:

->  Seq Scan on planet_osm_line l  (cost=0.00..209587.65 rows=4289865 width=270)

postgres leci po 4 milionach rekordów z planet_osm_line? Tylko na co powinienem dać w takim wypadku indeks?

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Wg mnie:

 

Tak, robi full scan po planet_osm_line (zaaliasowane jako l), bo join jest po tym: ST_DWithin(p.way, l.way, 0.1). Postgres nie potrafi użyć indexu, jeśli na zaindexowanej kolumnie jest wywołana funkcja w zapytaniu, a ST_DWithin na taką mi wygląda. Klapa, index nie zostanie wykorzystany.

 

Ja bym spróbował stworzyć materialized view z potrzebnymi Ci kolumnami tabel oraz kolumnami, które będą wyliczone z funkcji, które obecnie są w SQLach. Wtedy nakładasz na nie (kolumny materialized view) indexy i w SQL zamiast funkcji używasz odpowiednich kolumn stworzonego widoku.

 

Indexujesz to, co jest w WHERE i ON w SQLach.

Edytowane przez Karister

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się

  • Ostatnio przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

  • Tematy

  • Odpowiedzi

    • Witam, zamierzam sam zainstalować sobie monitoring wokoło domu i mam pytanie, ponieważ jestem laikiem. Czy można tak połączyć kamery za pomocą tych extenderów? 
    • Postaram się podrzucić następnym razem, jak będę na miejscu. Jak byłem ostatnio, to tyle pamiętam, że łapało LTE2100 z przekaźnika na odległości niecałych 4 km, a moc sięgała niżej niż -90dBm. Ogólnie tragedia z wczytaniem najprostszej strony internetowej, u 3 operatorów podobnie.   Powiem tak - została ta antena wybrana i zamontowana przez "fachowca" na zlecenie innych domowników. Ja się na tym tak nie znam, ale zanim się dowiedziałem jeszcze co tam w ogóle zostało zamontowane, to czułem już, że to będzie bubel, bo co innego może taki "fachowiec" zamontować. No i widzę, że moje przypuszczenia się potwierdzają. Żadnej poprawy to nie da? Bo trochę teraz ciężko będzie to zdjąć i rozmontować, nie wspominając już o poniesionych kosztach i ewentualnych następnych kosztach zakupu nowej anteny. Czy jesteś w stanie odpowiedzieć na resztę pytań dotyczących routera? Na przykład takie złącza to pewnie i tak zawsze będą te same, więc niezależnie od anteny router chyba można wybrać już teraz (mogę się mylić!). Chciałbym szczerze mieć coś ogarnięte przez majówką, o ile jest to osiągalne.
    • Witam po rocznej przerwie ; -). Odnawiam temat. Jak można łatwo odgadnąć, w poprzednim roku nic nie wyszło z kupna PC. Nic jednak straconego, gdyż jestem aktualnie gotowy do kupna gotowego zestawu lub zbudowania własnego PC. Budżet za samą jednostkę z softwarem (OS + Office) +/- 10000zł. Mogę dołożyć, o ile będzie miało to sens. Na początek, znalazłem taką oto promo w X-KOM: https://www.x-kom.pl/p/1220819-desktop-g4m3r-hero-i7-14700f-32gb-1tb-rtx4070s-w11x.html?sm=lowcygier Czy to dobra oferta? Czy też lepiej zbudować własną maszynę od zera?    
    • Świetne rady, autor tematu gra w 3440x1440, więc jakim cudem warto zmieniać 4070Ti na 4070Ti Super, skoro premiera RTX 5000 jest tak nieodległa ? Zanim braknie mu 12GB VRAM w tej rozdzielczości to będzie premiera RTX 6000. Więc @andriejek69 jak masz zmieniać teraz kartę to albo coś dużo mocniejszego, albo czekaj na nowe RTXy. Chyba, że faktycznie chcesz pograć w Cyberpanka z Path Tracingiem, ale tam nawet 4070Ti Super z 16GB to będzie za mało. Zrobisz ja uważasz, ale osobiście uważam taką zmanię za kompletnie bezsensowną, bo obecna kara Ci wystarczy do tej rozdzielczości, a jak zmieniać to na 4090, żeby faktycznie poczuć różnicę, teraz dostaniesz 10% to wydajności. Jedyna opcja to sprzedaż obecnej karty za dobrą cenę i niewielka dopłata.
    • Trudne się wylosowało... Monitorów z tunerem jest jak na lekartwo a szybszych niz 60hz tym bardziej. Nie ma mowy też o oledzie ani miniledzie z tunerem chyba że chodzi o telewizor to już prędzej coś znajdziesz.  Nie podałeś specyfikacji swojego komputera to też niezbyt można powiedzieć czy poradzi sobie z monitorem 4k np. (Samsung monitor m7 i m8) mają smart tv ale tunera już nie mają... Dodatkowo są na matrycy VA co nie każdemu może przypaść do gustu. Najlepszym rozwiązaniem będzie kupno możliwie najlepszego monitora na miniledzie/oled (jeżeli nadal mówimy o budżecie 4000zł) i jakiegoś smartboxa (googletv) z tunerem i podłączenie go do monitora poprzez HDMI.
  • Aktywni użytkownicy

×
×
  • Dodaj nową pozycję...