unaccent() 阻止 Postgres 中的索引使用

2023-11-26

我想从导入到 PostgreSQL 9.3.5 的 OpenStreetMap 数据库中检索给定名称的路线,操作系统是 Win7 64 位。为了具有一定的容错能力,我使用了 Postgres 的非重音扩展。

我的查询如下所示:

SELECT * FROM germany.ways
WHERE lower(tags->'name') like lower(unaccent('unaccent','Weststrasse'))

查询计划:

Seq Scan on ways  (cost=0.00..2958579.31 rows=122 width=465)
  Filter: (lower((tags -> 'name'::text)) ~~ lower(unaccent('unaccent'::regdictionary, 'Weststrasse'::text)))

奇怪的是,这个查询对方法使用顺序扫描,尽管索引存在于lower(tags->'name'):

CREATE INDEX ways_tags_name ON germany.ways (lower(tags -> 'name'));

一旦我从查询中删除非重音符号,Postgres 就会使用索引:

SELECT * FROM germany.ways
WHERE lower(tags->'name') like lower('Weststrasse')

查询计划:

Index Scan using ways_tags_name on ways  (cost=0.57..495.43 rows=122 width=465)
  Index Cond: (lower((tags -> 'name'::text)) = 'weststrasse'::text)
  Filter: (lower((tags -> 'name'::text)) ~~ 'weststrasse'::text)

为什么 unaccent 会阻止 Postgres 使用索引?在我看来,这是没有意义的,因为在执行实际查询之前,应该已经完全知道非重音符号(变音符号删除等)的结果。所以Postgres应该能够使用索引。使用unaccent时如何避免seq扫描?


IMMUTABLE的变体unaccent()

为了澄清其中的错误信息已接受,现已删除,答案不正确:
表达式索引仅允许IMMUTABLE功能(出于明显的原因)和unaccent()只是STABLE. The 您在评论中建议的解决方案也是有问题的。详细解释和正确的解决方案 for that:

  • PostgreSQL 是否支持“重音不敏感”排序规则?

取决于内容tags->name添加可能有用unaccent()到表达式索引,但这与为什么不使用索引的问题正交:

  • PostgreSQL 重音+不区分大小写的搜索

实际问题/解决方案

运营商LIKE在你的查询中是微妙的wrong(最有可能的)。你做not想要将“Weststrasse”解释为搜索模式,您希望按原样匹配(规范化)字符串。替换为=运算符,您将看到当前索引的(位图)索引扫描,不管的函数波动性unaccent():

SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))

Why?

的右操作数LIKE is a pattern。 Postgres 不能使用普通的 btree 索引进行模式匹配(例外情况适用). A LIKE使用纯字符串作为模式(无特殊字符)可以通过对 btree 索引进行相等检查来优化。但如果字符串中有特殊字符,this索引已出。

如果有一个IMMUTABLE函数的右边LIKE,可以立即评估,并且上述优化仍然是可能的。引用手册上函数波动类别:

IMMUTABLE ...
此类别允许优化器在以下情况下预先评估函数: 查询使用常量参数调用它。

如果函数波动性较小(STABLE or VOLATILE)。这就是为什么你的“解决方案”是伪造IMMUTABLE unaccent()看似有效,但实际上是给猪涂口红。

重申一下:

  • 如果您想与LIKE和模式,使用三元组GIN索引.
  • 如果您不想与LIKE和模式,使用相等运算符=(以及表达式上的 B 树索引lower(tags->'name').
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

unaccent() 阻止 Postgres 中的索引使用 的相关文章

随机推荐

  • 使用 powershell 在网页中查找特定句子

    我需要使用 powershell 通过 whois 解析 IP 地址 我的公司过滤端口 43 和 WHOIS 查询 因此我在这里必须使用的解决方法是要求 powershell 使用以下网站https who is 读取http流并查找与IP
  • 使用 C# 处理 Windows 8 应用商店应用程序中的 VirtualKey

    我知道如何处理关键事件 即 private void Page KeyUp object sender KeyRoutedEventArgs e switch e Key case Windows System VirtualKey Ent
  • 代码合约发生了什么?

    几年前 在 NET 4 发布之前 代码契约就已经遍布博客圈 NET 4 中包含的运行时组件以及更昂贵的 Visual Studio 2010 版本中提供的静态检查器 不过 围绕代码合约的讨论似乎已经平息 人们是否在生产中使用它 微软研究院还
  • 具有多个应用程序的 Tomcat 上的类加载器行为

    在 Tomcat 5 5 服务器上 我将一个类放入系统类路径中 并修改 catalina bat 以选择它 或者将类放入共享 lib 目录中 现在 如果我有两个不同的应用程序使用同一个类 而它们的 WEB INF lib classes 目
  • 如何在 WordPress 管理侧边栏添加自定义链接

    如何在不使用插件的情况下在 WordPress 管理侧边栏添加自定义链接 例如 我想添加 Google com 链接 我应该怎么做 我试过这个 将下一个代码添加到 admin bar php function mycustomlink gl
  • 为什么我需要 PHP 中的 isset() 函数?

    我试图理解这之间的区别 if isset POST Submit do something and if POST Submit do something 在我看来 如果 POST Submit 变量为 true 则它被设置 在这种情况下为
  • 使用类型名称将 JSON 文本反序列化为特定对象类型 [重复]

    这个问题在这里已经有答案了 我曾经使用下面的代码将 JSON 文本反序列化为强类型对象 Trainer myTrainer JsonConvert DeserializeObject
  • 如何在 Swift 中将字符串编码/解码为 Base64?

    我想将字符串转换为 Base64 我在几个地方找到了答案 但它在 Swift 中不再起作用 我使用的是 Xcode 6 2 我相信答案可能适用于以前的 Xcode 版本 而不适用于 Xcode 6 2 有人可以指导我在 Xcode 6 2
  • 从包含文件返回

    在 PHP 中 如何从包含的脚本返回到包含它的脚本 IE 1 主脚本 2 应用 3 包括 基本上 我想从 3 返回到 2 return 不起作用 2 应用程序中的代码 page User Manager if permission 13 1
  • TZupdater 因 tzdata2016g 版本失败

    TZUpdater 2 1 0 在 tzdata2016g 版本中失败 对于 Java 8 它会失败并显示 源目录不包含文件 VERSION 错误 而对于 Java 7 它会以 JRE 更新到版本 tzdataunknown 注释完成 其原
  • Firebase 可扩展性限制

    This post表示当单个节点开始拥有 1 10 百万个子节点时 FireBase 将遇到问题 如果应用程序中的用户超过 1000 万 应该如何处理 在所有示例中 我认为用户只是单个节点 用户 的子节点 Firebase 不适合处理长列表
  • 在 Emacs 上同时运行 Clojure 和其他 Lisp

    I use Aquamacs 并且 Aquamacs 预先配备了SLIME setq inferior lisp program usr local bin sbcl add to list load path Library Applic
  • 有没有可用于印度语言的词干分析器[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 是否有任何针对印度语言的词干分析器的实现 例如 印地语 泰卢固语 可用 印地语分析器 带有词干分析器 可在 Lucene 中使用 正是基于此算法 p
  • string1 >= string2 未在 Linq to SQL 中实现,有解决方法吗?

    如何在 Linq to SQL 中执行 string1 gt string2 如果您正在寻找 gt 通常会写成 gt 那么你不能直接用字符串来做到这一点 您可以通过以下方式获得相同的行为相比于 string1 CompareTo strin
  • 这是角度模板缓存清除的好方法吗?

    我正在尝试在我的角度应用程序上实现一些缓存清除 其方式仍然允许缓存 但在我们将新代码推送到生产环境时会破坏它 到目前为止 我的设置涉及使用 grunt 缓存破坏器https www npmjs org package grunt cache
  • 转到 HTML 中另一个页面的 div

    我想从不同的页面转到特定页面的 DIV 那可能吗 I tried a href file html product Hello a 但它只是去file html home thanks C 我的 file html 中有 但它不断被重定向到
  • Microchip PIC 的 Modbus 堆栈

    有人可以建议为 Microchip PIC18 处理器实现 Modbus RTU 从站的开源实现吗 我正在寻找 RS 232 RS 485 的 Modbus RTU 实现 但 Modbus TCP IP 实现也将受到欢迎 我已经为 PIC1
  • 如何在 IPython 笔记本中打开交互式 matplotlib 窗口?

    我正在使用 IPython pylab inline有时想要快速切换到交互式 可缩放的 matplotlib GUI 来查看绘图 当您在终端 Python 控制台中绘制某些内容时会弹出 我怎么能这么做呢 最好不要离开或重新启动我的笔记本 I
  • Android - 如何通过用户名以编程方式切换用户?

    我是 Android 新手 我必须在工作中创建一个执行以下任务的应用程序 我监听一个应该向我发送用户名的套接字 收到用户名后 我需要在平板电脑上切换到该用户帐户 如果我收到与当前活动用户相同的用户名 我不需要切换 显然 我们的平板电脑已获得
  • unaccent() 阻止 Postgres 中的索引使用

    我想从导入到 PostgreSQL 9 3 5 的 OpenStreetMap 数据库中检索给定名称的路线 操作系统是 Win7 64 位 为了具有一定的容错能力 我使用了 Postgres 的非重音扩展 我的查询如下所示 SELECT F