PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Maneira de tentar vários SELECTs até que um resultado esteja disponível?


LIKE sem caractere curinga é equivalente a = . Supondo que você realmente quis dizer name = 'text' .

Índices são a chave para o desempenho.

Configuração do teste

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

Idealmente, você cria dois índices (além da chave primária):
CREATE INDEX image_name_grp_idx ON image (name, group_id);
CREATE INDEX image_grp_idx ON image (group_id);

O segundo pode não será necessário, dependendo da distribuição dos dados e outros detalhes. Explicação aqui:
  • Um índice composto também é bom para consultas no primeiro campo?

Consulta


Este deve ser o mais rápido possível consulta para o seu caso:
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.

O LIMIT cláusula se aplica a toda a consulta. Postgres é inteligente o suficiente para não executar partes posteriores do UNION ALL assim que encontrar linhas suficientes para satisfazer o LIMIT . Consequentemente, para uma correspondência no primeiro SELECT da consulta, a saída de EXPLAIN ANALYZE se parece com isso (role para a direita! ):
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

Minha ênfase em negrito.

Não adicione um ORDER BY cláusula , isso anularia o efeito. Então o Postgres teria que considerar todas as linhas antes de retornar a linha superior.

Perguntas finais


Existe uma solução genérica para isso?

Isso é a solução genérica. Adicione o máximo de SELECT declarações como quiser.

Claro que seria útil quando o resultado da pesquisa fosse classificado por sua relevância.

Há apenas uma linha no resultado com LIMIT 1 . Tipo de classificação de vazios.