Mam stół z 50 000 rzędami. To właściwie tabela PostGIS.
Zapytanie składa się z 4 części (1 obowiązkowe) (3 opcjonalnie)
- pole przecięcia (prostokąt geograficzny) o długości 4 lat (używam st_intersects) [Obowiązkowe]
- Zakres dat (min., Maks.) W polu daty
- Typ pliku (zestaw do 8 wartości tekstowych) obecnie używa IN (.....), ale w razie potrzeby mogę utworzyć tabelę tymczasową. Widzę, że wiele osób nie lubi IN.
- Kraj (wartość tekstowa).
Oczekuję około 100 - 4000 zwróconych wierszy
Jeśli utworzę indeks złożony w tabeli, której kolumny powinienem użyć jako pierwszy. Drobnoziarnista to prawdopodobnie lokalizacja (dane są rozproszone po całym świecie). Obecnie mam go jako indeks GIST.
Pozostałe indeksy to BTREE.
Moja intuicja mówi, że używaj drobnoziarnistych i oczywiście na końcu. Np. Istnieje tylko około 12 typów plików, więc byłyby to bardzo duże segmenty dla indeksu.
Co mówią guru PostgreSQL i PostGIS (którzy znają wewnętrzne elementy systemu)?
AKTUALIZACJA:
Pozwól, że wyostrzę to pytanie.
- Nie chcę, żeby ktokolwiek musiał wykonywać pracę, którą powinienem wykonać. Za bardzo szanuję twój czas. Przejdę więc do wyjaśnienia przeanalizuj później.
- Szukałem jedynie wskazówek, wskazówek i wskazówek.
- Przeczytałem ten znakomity mały post: https://devcenter.heroku.com/articles/postgresql-indexes#managing-and-maintaining-indexes o indeksach
- Zwykle tworzę 4 osobne indeksy (geo-box, nazwa kraju, typ pliku i data), ale chcę zobaczyć, co zrobiłoby zapytanie złożone.
Powiedz mi, czy którekolwiek z tych założeń są błędne. (Jestem całkiem nowy w koncepcji indeksów złożonych)
- Porządek jest ważny. Wybierz jako pierwszy indeks ten, który najbardziej wycina wiersze (w moim przypadku najlepiej sprawdziłaby się lokalizacja (geografia), która jest prostym wielokątem lub wielokątem).
- Czasami zapytania pomijają indeksy. Ale jeśli utworzę zapytanie złożone z kluczem (# 1, # 2, # 3, # 4), to nawet jeśli użytkownik utworzy coś, co prosi o # 1, # 3, planista nadal będzie używał pojedynczego zapytania złożonego, ponieważ zamawia jest obsługiwany.
- Normalnie tworzyłbym trzy zapytania BTREE i jedno GIST (dla typu geograficznego). PostGIS nie obsługuje tworzenia związku z wielu typów indeksów. Będę musiał użyć GIST indeksu złożonego. Ale to nie powinno boleć.
- Jeśli utworzę dodatkowe indeksy złożone lub pojedyncze wartości, planista jest wystarczająco inteligentny, aby wybrać najbardziej inteligentny .....
- Nazwa kraju może mieć około 250 różnych wartości i jest oczywiście silnie powiązana z lokalizacją (geobox), ale jeśli kolejnym najlepszym indeksem do zmniejszenia rozmiaru wiersza jest typ_pliku, powinienem go użyć. Nie oczekuję, że użytkownicy często używają kraju lub daty w swoich zestawach zapytań.
- NIE muszę się martwić, że utworzenie indeksu złożonego z 4 kluczy znacznie zwiększy rozmiar danych indeksu. Tzn. Jeśli indeks jednego klucza wyniesie 90% wzrostu wydajności, nie zaszkodzi dodać 3 dodatkowe elementy, aby je zwiększyć. I odwrotnie, powinienem naprawdę utworzyć oba indeksy. Pojedynczy indeks geograficzny, a także indeks złożony i pozwól planistowi ustalić, który jest najlepszy, i weźmie pod uwagę rozmiar tabeli indeksów.
Ponownie, nie proszę nikogo o zaprojektowanie mojego rozwiązania, nie myślę o pracy innych. Ale potrzebuję rzeczy, których dokumentacja PostGreSQL nie mówi mi o implementacji
[Powodem, dla którego nie mam jeszcze wyniku WYJAŚNIENIA, jest to, że muszę utworzyć tę tabelę wierszy o wielkości 25 000 z tabeli wierszy o wielkości 24 mln. To zajmuje więcej czasu, niż myślałem. Grupuję rzeczy w 1000 grup przedmiotów i pozwalam użytkownikowi zapytać o tabelę wierszy o wielkości 25 KB. Ale moje następne pytanie będzie wymagało użycia wyników tego zapytania, aby przejść do tabeli wierszy MASTER 25M i wyciągnąć różne rzeczy, i to tam wydajność indeksu złożonego naprawdę HIT].
przykładowe zapytanie poniżej:
SELECT
public.product_list_meta_mv.cntry_name AS country,
public.product_list_meta_mv.product_producer AS producer,
public.product_list_meta_mv.product_name AS prod_name,
public.product_list_meta_mv.product_type AS ptype,
public.product_list_meta_mv.product_size AS size,
ST_AsGeoJSON(public.product_list_meta_mv.the_geom, 10, 2) AS outline
FROM
public.product_list_meta_mv
WHERE
public.product_list_meta_mv.cntry_name = 'Poland'
AND
ST_Intersects(public.product_list_meta_mv.the_geom,
st_geogfromtext('SRID=4326;POLYGON((21.23107910156250 51.41601562500000,
18.64379882812500 51.41601562500000,
18.64379882812500 48.69415283203130,
21.23107910156250 48.69415283203130,
21.23107910156250 51.41601562500000))'))
AND (date >= '1/2/1900 5:00:00 AM'
AND date <= '2/26/2014 10:26:44 PM')
AND (public.product_list_meta_mv.product_type in
('CIB10','DTED0','DTED1','DTED2','CIB01','CIB05')) ;
WYJAŚNIJ wyniki ANALIZY (nie wprowadziłem żadnych indeksów złożonych, a od prędkości, którą widzę, nie wiem, czy muszę).
"Bitmap Heap Scan on catalog_full cat (cost=4.33..37.49 rows=1 width=7428) (actual time=1.147..38.051 rows=35 loops=1)"
" Recheck Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
" Filter: (((type)::text = ANY ('{CADRG,CIB10,DTED1,DTED2}'::text[])) AND (_st_distance('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography, outline, 0::double precision, false) < 1e-005::double precision))"
" Rows Removed by Filter: 61"
" -> Bitmap Index Scan on catalog_full_outline_idx (cost=0.00..4.33 rows=8 width=0) (actual time=0.401..0.401 rows=96 loops=1)"
" Index Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
"Total runtime: 38.109 ms"
EXPLAIN ANALYZE SELECT pid,product_name,type,country,date,size,cocom,description,egpl_date,ST_AsGeoJSON(outline, 10, 2) AS outline
FROM portal.catalog_full AS cat
WHERE ST_Intersects(st_geogfromtext('SRID=4326;POLYGON((21.2200927734375 51.38031005859375, 18.65478515625 51.38031005859375, 18.65478515625 48.7298583984375, 21.2200927734375 48.7298583984375, 21.2200927734375 51.38031005859375))'), cat.outline)
AND (cat.type in ('CADRG','CIB10','DTED1','DTED2'))
EXPLAIN ANALYZE
zapytanie.