sql >> Database >  >> RDS >> PostgreSQL

Manier om meerdere SELECT's te proberen totdat een resultaat beschikbaar is?

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.



  1. Update meerdere kolommen in MERGE-instructie ORACLE

  2. Kan geen verbinding maken met de Oracle-database met behulp van JDBC als het wachtwoord speciale tekens heeft

  3. Hoe de SQL Server DIFFERENCE()-functie werkt

  4. MySQL:ALTER NEGEER TABEL UNIEK TOEVOEGEN, wat wordt afgekapt?