LIKE
bez znaku wieloznacznego jest równoważne =
. Zakładając, że rzeczywiście miałeś na myśli name = 'text'
.
Indeksy są kluczem do wydajności.
Konfiguracja testowa
CREATE TABLE image (
image_id serial PRIMARY KEY
, group_id int NOT NULL
, name text NOT NULL
);
Najlepiej, jeśli utworzysz dwa indeksy (oprócz klucza podstawowego):
CREATE INDEX image_name_grp_idx ON image (name, group_id);
CREATE INDEX image_grp_idx ON image (group_id);
Drugi może nie być konieczne, w zależności od dystrybucji danych i innych szczegółów. Wyjaśnienie tutaj:
- Czy indeks złożony jest również odpowiedni dla zapytań w pierwszym polu?
Zapytanie
To powinno być najszybsze z możliwych zapytanie dotyczące Twojej sprawy:
SELECT * FROM image WHERE name = 'name105' AND group_id = 10
UNION ALL
SELECT * FROM image WHERE name = 'name105'
UNION ALL
SELECT * FROM image WHERE group_id = 10
LIMIT 1;
Skrzypce SQL.
LIMIT
klauzula dotyczy całego zapytania. Postgres jest wystarczająco sprytny, nie uruchamia się późniejsze odnogi UNION ALL
jak tylko znajdzie wystarczającą liczbę wierszy, aby spełnić LIMIT
. W związku z tym dla dopasowania w pierwszym SELECT
zapytania, wyjście EXPLAIN ANALYZE
wygląda tak (przewiń w prawo! ):
Limit (cost=0.00..0.86 rows=1 width=40) (actual time=0.045..0.046 rows=1 loops=1) Buffers: local hit=4 -> Result (cost=0.00..866.59 rows=1002 width=40) (actual time=0.042..0.042 rows=1 loops=1) Buffers: local hit=4 -> Append (cost=0.00..866.59 rows=1002 width=40) (actual time=0.039..0.039 rows=1 loops=1) Buffers: local hit=4 -> Index Scan using image_name_grp_idx on image (cost=0.00..3.76 rows=2 width=40) (actual time=0.035..0.035 rows=1 loops=1) Index Cond: ((name = 'name105'::text) AND (group_id = 10)) Buffers: local hit=4 -> Index Scan using image_name_grp_idx on image (cost=0.00..406.36 rows=500 width=40) (never executed) Index Cond: (name = 'name105'::text) -> Index Scan using image_grp_idx on image (cost=0.00..406.36 rows=500 width=40) (never executed) Index Cond: (group_id = 10) Total runtime: 0.087 ms
Pogrubiony nacisk na moje.
Nie nie dodaj ORDER BY
klauzula , unieważniłoby to skutek. Wtedy Postgres musiałby rozważyć wszystkie wiersze przed zwróceniem górnego wiersza.
Pytania końcowe
Czy istnieje na to ogólne rozwiązanie?
To jest ogólne rozwiązanie. Dodaj tyle SELECT
oświadczenia, jak chcesz.
Oczywiście przydałoby się to, gdy wynik wyszukiwania jest sortowany według jego trafności.
W wyniku jest tylko jeden wiersz z LIMIT 1
. Rodzaj sortowania pustych przestrzeni.