LIKE
zonder jokerteken is gelijk aan =
. Ervan uitgaande dat je eigenlijk name = 'text'
. bedoelde .
Indexen zijn de sleutel tot prestaties.
Testopstelling
CREATE TABLE image (
image_id serial PRIMARY KEY
, group_id int NOT NULL
, name text NOT NULL
);
Idealiter maakt u twee indexen (naast de primaire sleutel):
CREATE INDEX image_name_grp_idx ON image (name, group_id);
CREATE INDEX image_grp_idx ON image (group_id);
De tweede mei niet nodig zijn, afhankelijk van de gegevensdistributie en andere details. Uitleg hier:
- Is een samengestelde index ook goed voor zoekopdrachten op het eerste veld?
Zoekopdracht
Dit zou de snelst mogelijke moeten zijn vraag voor uw geval:
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;
SQL Fiddle.
De LIMIT
clausule is van toepassing op de hele zoekopdracht. Postgres is slim genoeg niet uit te voeren latere etappes van de UNION ALL
zodra het voldoende rijen heeft gevonden om te voldoen aan de LIMIT
. Bijgevolg, voor een wedstrijd in de eerste SELECT
van de query, de uitvoer van EXPLAIN ANALYZE
ziet er zo uit (scroll naar rechts! ):
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
Vetgedrukte nadruk van mij.
Doe niet voeg een ORDER BY
toe clausule , dit zou het effect teniet doen. Dan zou Postgres alle rijen moeten overwegen voordat de bovenste rij wordt geretourneerd.
Laatste vragen
Is daar een generieke oplossing voor?
Dit is de generieke oplossing. Voeg zoveel SELECT
toe verklaringen zoals je wilt.
Het zou natuurlijk handig zijn als het zoekresultaat is gesorteerd op relevantie.
Er is slechts één rij in het resultaat met LIMIT 1
. Soort van leegtes sorteren.