PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Möglichkeit, mehrere SELECTs auszuprobieren, bis ein Ergebnis verfügbar ist?

LIKE ohne Platzhalterzeichen entspricht = . Angenommen, Sie meinten tatsächlich name = 'text' .

Indizes sind der Schlüssel zur Leistung.

Testaufbau

CREATE TABLE image (
  image_id serial PRIMARY KEY
, group_id int NOT NULL
, name     text NOT NULL
);

Idealerweise erstellen Sie zwei Indizes (zusätzlich zum Primärschlüssel):

CREATE INDEX image_name_grp_idx ON image (name, group_id);
CREATE INDEX image_grp_idx ON image (group_id);

Die zweite darf je nach Datenverteilung und anderen Details nicht erforderlich sein. Erklärung hier:

  • Ist ein zusammengesetzter Index auch gut für Abfragen im ersten Feld?

Abfrage

Dies sollte so schnellstmöglich sein Abfrage für Ihren Fall:

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-Geige.

Das LIMIT Klausel gilt für die gesamte Abfrage. Postgres ist schlau genug, nicht auszuführen spätere Abschnitte von UNION ALL sobald es genügend Zeilen gefunden hat, um das LIMIT zu erfüllen . Folglich für eine Übereinstimmung in der ersten SELECT der Abfrage, die Ausgabe von EXPLAIN ANALYZE sieht so aus (nach rechts scrollen! ):

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

Fettdruck von mir.

Tut nicht Fügen Sie einen ORDER BY hinzu Klausel , würde dies den Effekt aufheben. Dann müsste Postgres alle Zeilen berücksichtigen, bevor es die oberste Zeile zurückgibt.

Abschlussfragen

Gibt es dafür eine generische Lösung?

Das ist die generische Lösung. Fügen Sie so viele SELECT hinzu Aussagen, wie Sie wollen.

Natürlich wäre es praktisch, wenn das Suchergebnis nach Relevanz sortiert wäre.

Es gibt nur eine Zeile im Ergebnis mit LIMIT 1 . Art der Leersortierung.