尝试多个SELECT直到结果可用的方法?

如果我想要以递减精度search表中的单个行,例如:

SELECT * FROM image WHERE name LIKE 'text' AND group_id = 10 LIMIT 1 

当这不给我结果,试试这个:

 SELECT * FROM image WHERE name LIKE 'text' LIMIT 1 

而当这不给我结果,试试这个:

 SELECT * FROM image WHERE group_id = 10 LIMIT 1 

只用一个expression式就可以做到这一点吗?

当我没有两个但是例如三个或更多个search参数时,也会出现问题。 有没有一个通用的解决scheme? 当search结果按其相关性sorting时,它当然会派上用场。

没有通配符的LIKE相当于= 。 假设你的意思是name = 'text'

索引是性能的关键。

testing设置

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

理想情况下,您创build两个索引(除了主键):

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

第二个可能没有必要,这取决于数据分布和其他细节。 这里解释:

  • 一个复合索引是否也适用于第一个字段的查询?

询问

这应该是你的情况下最快的查询:

 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小提琴。

LIMIT子句适用于整个查询。 Postgres足够聪明,只要find足够的行来满足LIMIT ,就不会执行 UNION ALL后面的LIMIT 。 因此,对于查询的第一个 SELECT中的匹配, EXPLAIN ANALYZE的输出如下所示( 滚动到右侧! ):

限制(成本= 0.00..0.86行= 1宽度= 40)(实际时间= 0.045..0.046行= 1个循环= 1)
  缓冲区:本地命中= 4
   - >结果(成本= 0.00..866.59行= 1002宽度= 40)(实际时间= 0.042..0.042行= 1个循环= 1)
        缓冲区:本地命中= 4
         - >追加(成本= 0.00..866.59行= 1002宽度= 40)(实际时间= 0.039..0.039行= 1循环= 1)
              缓冲区:本地命中= 4
               - >在图像上使用image_name_grp_idx进行索引扫描(cost = 0.00..3.76 rows = 2 width = 40)(实际时间= 0.035..0.035 rows = 1 loops = 1 )
                    索引条件:((name ='name105':: text)AND(group_id = 10))
                    缓冲区:本地命中= 4
               - >索引扫描使用图像上的image_name_grp_idx(成本= 0.00..406.36行= 500宽度= 40) (从未执行)
                    索引条件:(name ='name105':: text)
               - >在图像上使用image_grp_idx进行索引扫描(成本= 0.00..406.36行= 500宽度= 40) (从不执行)
                    索引条件:(group_id = 10)
总运行时间:0.087毫秒 

大胆重视我的。

不要添加ORDER BY子句 ,这会使效果无效。 然后Postgres将不得不考虑所有的行之前返回的第一行。

最后的问题

有没有一个通用的解决scheme?

通用的解决scheme。 根据需要添加尽可能多的SELECT语句。

当search结果按其相关性sorting时,它当然会派上用场。

结果中只有一行有LIMIT 1 。 种类空隙sorting。

这是迟到了,我不想写出一个完整的解决scheme,但如果我需要这个,我可能会创build一个客户函数 ,返回一个客户types,logging或表(根据您的需要)。 这样做的好处是,一旦你find你的logging,你可以停下来。

使参数的数量变得有活力将使其更具挑战性。 根据您的PostgreSQL版本(以及您可以使用的扩展名),您可能可以传入hstore或json并dynamic构build查询。

也许不是最好的答案,但它不仅仅是一个评论,并希望有一些思想的食物。

我不认为在find你想要的结果之前单独运行这些查询是没有问题的。 虽然有办法将这些结合成一个查询,但最终会变得更复杂和更慢,这不是你想要的。

您应该运行考虑在一个事务中运行所有查询,可能在可重复读取隔离级别上最好,这样可以获得一致的结果,同时也可以避免设置重复事务的开销。 另外,如果您明智地使用预准备语句,那么在一个组合语句中运行所有三个查询的开销几乎相同。

 SELECT *, CASE WHEN name like 'text' AND group_id = 10 THEN 1 WHEN name like 'text' THEN 2 WHEN group_id = 10 THEN 3 ELSE 4 END ImageRank FROM image WHERE ImageRank <> 4 ORDER BY ImageRank ASC LIMIT 1 

这将是一个伪解决scheme,但我不完全确定您的scheme中的语法是否允许