Optymalizacja zapytania i tabeli - wolne zwracanie wyników

0

Witajcie.
Mam bazę danych adresów (PostgreSQL):

CREATE TABLE adresy (
	id serial4 NOT NULL,
	prg_id text NULL,
	kod text NULL,
	miasto text NULL,
	ulica text NULL,
	numer text NULL,
	powiat text NULL,
	adres text NULL
);
CREATE UNIQUE INDEX adresy_id_pkey ON adresyg USING btree (id);

Baza w sumie ma parę GB.
id = id rekordu w bazie,
kod = kod pocztowy,
ulica = ulica,
numer = numer domu,
powiat = powiat,
adres = kod pocztowy miasto ulica numer

Mam problem z zapytaniami typu:

  • SELECT ulica, kod, miasto, numer, similarity('ulica' , '$address') AS similarity, row_number() OVER () AS rank FROM adresy where ulica LIKE '%$address%' and miasto = '$miejsce' and kod = '$kod' order by rank LIMIT 1;
  • SELECT ulica, kod, miasto, ulica <-> '$address' AS distance, row_number() OVER () AS rank FROM adresy WHERE miasto = '$miejsce' and kod = '$kod' ORDER BY distance LIMIT 1;

(zwrócenie wyniku trwa nawet 15 sekund).

funkcja similarity wygląda tak:

CREATE OR REPLACE FUNCTION public.similarity(text, text)
 RETURNS real
 LANGUAGE c
 IMMUTABLE PARALLEL SAFE STRICT
AS '$libdir/pg_trgm', $function$similarity$function$
;

Wie ktoś może jak można zoptymalizować zapytanie lub bazę / tabelę?

1

Ile masz danych w tej bazie? Wszelkie zabawy z wyszukiwaniem podobnych są wymagające obliczeniowo. Bez konkretnej analizy co tak naprawdę spowalnia te zapytania trudno coś tu powiedzieć. Wywal similarity i zobacz jak to wtedy działa.
I nie dokońca wioem co tu ktoś chce osiągnąć:

row_number() OVER () AS rank

Wyliczanie tego w ten sposób, a potem sortowanie po jest kolumnie jest dziwne.

1

dodaj indeks na miasto i kod (jeden indeks na dwa pola!) i zobacz czy pomoże.

A na przyszłość baza ma coś takiego jak analizator planu zapytania - użyj go albo chociaż pokaż nam jak wygląda dla problematycznego zapytania

1
  1. Oczywiście, tak jak pisał @abrakadaber indeks na dwa pola (miasto, kod) - NIE index unikalny, tylko "zwykły". Możesz go również hash zrobić - wg moich doświadczeń troszkę szzybszy jest. Wceśniej zamień typy tych pól na VARCHAR, zamiast TEXT. W "kod" możesz nawet dać VARCHAR(6).
  2. Zapytanie typu SELECT ulica, kod, miasto, numer, similarity('ulica' , '$address') AS similarity, row_number() OVER () AS rank FROM adresy where ulica LIKE '%$address%' and miasto = '$miejsce' and kod = '$kod' order by rank LIMIT 1; zamień na With x as (SELECT ulica, kod, miasto, numer, row_number() OVER () AS rank FROM adresy where ulica LIKE '%$address%' and miasto = '$miejsce' and kod = '$kod' order by rank LIMIT 1) SELECT ulica, kod, miasto, numer, similarity('ulica' , '$address') AS similarity, rank FROM x - nie będzie ci wtedy "zewnetrznej" funkcji uzywał do wszystkich rekordów, tylko do potrzebnego

EDIT: przecinek w SQL

1 użytkowników online, w tym zalogowanych: 0, gości: 1