nep*_*epa 5 sql postgresql union postgresql-performance
如果我想以递减精度搜索表中的单行,例如:
SELECT * FROM image WHERE name LIKE 'text' AND group_id = 10 LIMIT 1
Run Code Online (Sandbox Code Playgroud)
如果这没有给我结果,请尝试这个:
SELECT * FROM image WHERE name LIKE 'text' LIMIT 1
Run Code Online (Sandbox Code Playgroud)
当这没有给我结果时,尝试这个:
SELECT * FROM image WHERE group_id = 10 LIMIT 1
Run Code Online (Sandbox Code Playgroud)
是否可以只用一种表达方式来做到这一点?
当我没有两个而是例如三个或更多搜索参数时,也会出现问题。有通用的解决方案吗?当然,当搜索结果按相关性排序时,它会派上用场。
CREATE TABLE image (
image_id serial PRIMARY KEY
, group_id int NOT NULL
, name text NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
索引是性能的关键因素。理想情况下,除了主键之外,您还创建这两个:
CREATE INDEX image_name_grp_idx ON image (name, group_id);
CREATE INDEX image_grp_idx ON image (group_id);
Run Code Online (Sandbox Code Playgroud)
第二个可能不是必需的,具体取决于数据分布和其他细节。看:
更新:Parallel Append
当用于大型集合时,这在 Postgres 11 或更高版本中变得不可靠!考虑这个问题和答案(包括我的答案中的可靠替代方案):
对于您的情况,这应该是最快的查询:
CREATE INDEX image_name_grp_idx ON image (name, group_id);
CREATE INDEX image_grp_idx ON image (group_id);
Run Code Online (Sandbox Code Playgroud)
LIKE
没有通配符相当于=
该LIMIT
子句适用于整个查询。Postgres 足够聪明,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 进行索引扫描(成本=0.00..3.76行=2宽度=40)(实际时间=0.035..0.035行=1循环=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 在返回顶行之前必须考虑所有行。
有通用的解决方案吗?
这是通用解决方案。添加SELECT
任意数量的语句。
当然,当搜索结果按相关性排序时,它会派上用场。
结果中只有一行LIMIT 1
。一种空洞排序。