LIKE
sans caractère générique équivaut à =
. En supposant que vous vouliez réellement dire name = 'text'
.
Index sont la clé de la performance.
Configuration du test
CREATE TABLE image (
image_id serial PRIMARY KEY
, group_id int NOT NULL
, name text NOT NULL
);
Idéalement, vous créez deux index (en plus de la clé primaire) :
CREATE INDEX image_name_grp_idx ON image (name, group_id);
CREATE INDEX image_grp_idx ON image (group_id);
Le deuxième peut pas nécessaire, selon la distribution des données et d'autres détails. Explication ici :
- Un index composite est-il également adapté aux requêtes sur le premier champ ?
Requête
Cela devrait être le plus rapide possible requête pour votre cas :
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.
La LIMIT
clause s'applique à l'ensemble de la requête. Postgres est suffisamment intelligent pour ne pas s'exécuter étapes ultérieures de l'UNION ALL
dès qu'il a trouvé suffisamment de lignes pour satisfaire la LIMIT
. Par conséquent, pour un match dans la première SELECT
de la requête, la sortie de EXPLAIN ANALYZE
ressemble à ceci (faites défiler vers la droite ! ):
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
J'insiste sur moi.
Ne pas ajouter un ORDER BY
clause , cela annulerait l'effet. Ensuite, Postgres devrait considérer toutes les lignes avant de renvoyer la ligne du haut.
Questions finales
Existe-t-il une solution générique pour cela ?
Ceci est la solution générique. Ajouter autant de SELECT
déclarations comme vous le souhaitez.
Bien sûr, cela serait utile lorsque le résultat de la recherche est trié par pertinence.
Il n'y a qu'une seule ligne dans le résultat avec LIMIT 1
. Type de tri des vides.