在 PostgreSQL 中查找有序字符串的精确、前缀和后缀匹配的有效方法
Efficient way to find ordered string's exact, prefix and postfix match in PostgreSQL
给定一个 table 名称 table
和一个名为 column
的字符串列,我想按以下方式在该列中搜索单词 word
:exact匹配项位于顶部,然后是前缀匹配项,最后是后缀匹配项。
目前我得到的解决方案如下:
解决方案 1:
select column
from (select column,
case
when column like 'word' then 1
when column like 'word%' then 2
when column like '%word' then 3
end as rank
from table) as ranked
where rank is not null
order by rank;
解决方案 2:
select column
from table
where column like 'word'
or column like 'word%'
or column like '%word'
order by case
when column like 'word' then 1
when column like 'word%' then 2
when column like '%word' then 3
end;
现在我的问题是,这两种解决方案中哪一种更有效或更好,是否有比这两种解决方案都更好的解决方案?
你的第二个解决方案看起来更易于规划器优化,但第一个解决方案也可能得到相同的计划。
对于 Where,不需要,因为它已包含在 ;它可能会使数据库混淆以进行 2 次检查而不是一次检查。
但最大的问题是第三个,因为它没有办法通过索引进行优化。
因此,无论哪种方式,PostgreSQL 都会扫描您的完整 table 并手动提取匹配项。这对于 20,000 行或更多行来说会很慢。
我建议您探索模糊字符串匹配和全文搜索;看起来这就是您要模拟的内容。
即使您不想要 FTS 或模糊字符串匹配的全部功能,您也绝对应该添加扩展 "pgtrgm",因为它可以让您在列上添加 GIN 索引,从而加快速度LIKE '%word' 搜索。
https://www.postgresql.org/docs/current/pgtrgm.html
说真的,看看 FTS。它确实提供排名。如果您的要求严格到您描述的内容,您仍然可以对 "prefilter" 执行 FTS 查询,然后再应用此逻辑。
关于 PostgreSQL FTS 的介绍文章很多,这里是一篇:
https://www.compose.com/articles/mastering-postgresql-tools-full-text-search-and-phrase-search/
甚至我最近在将 FTS 搜索添加到我的站点时写了一个 post:
https://deavid.wordpress.com/2019/05/28/sedice-adding-fts-with-postgresql-was-really-easy/
给定一个 table 名称 table
和一个名为 column
的字符串列,我想按以下方式在该列中搜索单词 word
:exact匹配项位于顶部,然后是前缀匹配项,最后是后缀匹配项。
目前我得到的解决方案如下:
解决方案 1:
select column
from (select column,
case
when column like 'word' then 1
when column like 'word%' then 2
when column like '%word' then 3
end as rank
from table) as ranked
where rank is not null
order by rank;
解决方案 2:
select column
from table
where column like 'word'
or column like 'word%'
or column like '%word'
order by case
when column like 'word' then 1
when column like 'word%' then 2
when column like '%word' then 3
end;
现在我的问题是,这两种解决方案中哪一种更有效或更好,是否有比这两种解决方案都更好的解决方案?
你的第二个解决方案看起来更易于规划器优化,但第一个解决方案也可能得到相同的计划。
对于 Where,不需要,因为它已包含在 ;它可能会使数据库混淆以进行 2 次检查而不是一次检查。
但最大的问题是第三个,因为它没有办法通过索引进行优化。
因此,无论哪种方式,PostgreSQL 都会扫描您的完整 table 并手动提取匹配项。这对于 20,000 行或更多行来说会很慢。
我建议您探索模糊字符串匹配和全文搜索;看起来这就是您要模拟的内容。
即使您不想要 FTS 或模糊字符串匹配的全部功能,您也绝对应该添加扩展 "pgtrgm",因为它可以让您在列上添加 GIN 索引,从而加快速度LIKE '%word' 搜索。
https://www.postgresql.org/docs/current/pgtrgm.html
说真的,看看 FTS。它确实提供排名。如果您的要求严格到您描述的内容,您仍然可以对 "prefilter" 执行 FTS 查询,然后再应用此逻辑。
关于 PostgreSQL FTS 的介绍文章很多,这里是一篇: https://www.compose.com/articles/mastering-postgresql-tools-full-text-search-and-phrase-search/
甚至我最近在将 FTS 搜索添加到我的站点时写了一个 post: https://deavid.wordpress.com/2019/05/28/sedice-adding-fts-with-postgresql-was-really-easy/