涉及 OR 条件的高级索引 (pgsql)

2023-12-13

我开始更好地掌握 PostgreSQL 索引,但我遇到了 OR 条件的问题,我不知道如何优化索引以实现更快的查询。

我有 6 个条件,当单独运行时,它们的成本似乎很小。以下是修剪查询的示例,包括查询计划计算时间。

(注意:为了降低复杂性,我没有输出下面这些查询的实际查询计划,但它们都使用nested loop left joins and index scans正如我所期望的那样,通过适当的索引。如有必要,我可以包含查询计划以获得更有意义的响应。)

EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions1)
 LIMIT 10;

QUERY PLAN
-------------------------------------------------------------------------------------
Limit  (cost=0.25..46.69 rows=1 width=171) (actual time=0.031..0.031 rows=0 loops=1)

EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions2)
 LIMIT 10;

QUERY PLAN
-------------------------------------------------------------------------------------
Limit  (cost=0.76..18.97 rows=1 width=171) (actual time=14.764..14.764 rows=0 loops=1)

/* snip */

EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions6)
 LIMIT 10;

QUERY PLAN
-------------------------------------------------------------------------------------
Limit  (cost=0.51..24.48 rows=1 width=171) (actual time=0.252..5.332 rows=10 loops=1)

我的问题是我想用 OR 运算符将这 6 个条件连接在一起,使每个条件都成为可能。我的组合查询看起来更像是这样:

EXPLAIN ANALYZE SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions1 OR conditions2 OR conditions3 OR conditions4 OR conditions5 OR conditions 6)
 LIMIT 10;

不幸的是,这导致查询计划大量增加,该计划似乎不再使用我的索引(相反,选择执行hash left join而不是一个nested loop left join,并进行各种sequence scans超过之前使用的index scans).

Limit  (cost=142.62..510755.78 rows=1 width=171) (actual time=30.591..30.986 rows=10 loops=1)

关于 OR 条件的索引,我应该知道什么特别的事情可以改善我的最终查询?

UPDATE:如果我对每个单独的 SELECT 使用 UNION,这似乎会加快查询速度。但是,如果我将来选择订购结果,这会阻止我订购结果吗?以下是我通过 UNION 加速查询所做的事情:

EXPLAIN ANALYZE
SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions1)
UNION
SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions2)
UNION
SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions3)
UNION
SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions4)
UNION
SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions5)
UNION
SELECT t1.*, t2.*, t3.*
  FROM t1 LEFT JOIN t2 on t2.id = t1.t2_id LEFT JOIN t3 ON t3.id = t1.t3_id
 WHERE (conditions6)
 LIMIT 10;

QUERY PLAN
-------------------------------------------------------------------------------------
Limit  (cost=219.14..219.49 rows=6 width=171) (actual time=125.579..125.653 rows=10 loops=1)

根据条件的不同,使用任何索引来帮助复杂的条件在逻辑上可能是不可能的OR表达式。

与 MySQL 一样,PostgreSQL 8.0 及更早版本的状态关于索引的文档:

请注意,查询或数据操作命令每个表最多可以使用一个索引。

在 PostgreSQL 8.1 中,这已经changed.

但是,如果这没有帮助,您可以使用UNION您尝试过的解决方案(这是 MySQL 用户的常见解决方案,它仍然有每个表一个索引的限制)。

您应该能够订购结果UNION查询,但必须使用括号来指定ORDER BY适用于结果UNION,而不仅仅是链中的最后一个子查询。

(SELECT ... )
UNION
(SELECT ... )
UNION
(SELECT ... )
ORDER BY columnname;

我希望这有帮助;我不是 PostgreSQL 优化器方面的专家。您可以尝试搜索邮件列表档案,或询问IRC频道.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

涉及 OR 条件的高级索引 (pgsql) 的相关文章

随机推荐

  • 数据库设计:复合键与一列主键

    我们的 Web 应用程序的数据库包含两个表 States idStates State Lat Long idStates是一个自增主键 Cities idAreaCode idStates City Lat Long idAreaCode
  • 分支逻辑测验——我哪里出错了? [JavaScript]

    我正在尝试为 简单 jQuery 测验开发逻辑 这里小提琴 问题是 问题路径有些动态 并产生树结构 例如 第一个问题是关于宠物 狗 猫还是鸟 如果您选择狗 它会询问狗的品种 如果您选择猫 它会询问猫的品种 等等 然后深入研究 这个特定品种的
  • ruby 中“do .. end”和“{..}”块的不同行为[重复]

    这个问题在这里已经有答案了 抱歉 如果这个问题重复 但我找不到用法上的区别 当我运行下面的代码时 我得到了不同的答案 我从大多数教程中看到 使用 do end 与 块相同 include Comparable a 1 4 2 3 5 p a
  • 如何使用实体框架 4.x 动态选择表?

    假设我有一个名为MyDatabase有两张桌子 MyTable1 and MyTable2 使用 Entity Framework 4 x 和 NET 4 的 Code First 方法 我生成了一个名为的上下文MyDatabaseCont
  • CSS中使用渐变效果反射文本

    我需要用 CSS 反射文本并为其添加渐变 这是一个例子我想要的 但我不想要具有 alpha 透明度的淡出 png 图像因为身体有背景 https jsfiddle net 9318Ltkp slogan font size 30px lin
  • 仅存档时出现 ARC 语义问题“多个名为‘setRotation’的方法”

    我在 cocos2dv3 中的项目正在抛出ARC语义问题发现多个名为 setRotation 的方法 其结果 参数类型或属性不匹配 归档时 发布模式 它在部署到模拟器 设备 调试模式 时运行良好 在发布模式下 编译器会混淆旋转的实现UIRo
  • 如何使安全令牌在被动 STS 设置中自动过期?

    我为我正在开发的新应用程序设置了被动 STS 我注意到 当用户的会话过期时 该用户仍然经过身份验证 我本以为当会话过期时 用户将不再被验证 我的老板与我讨论了这个问题 因为我目前负责设置身份验证 他说 如果我们能让用户的登录在一段时间内不活
  • 崩溃加载可穿戴活动

    将 AppCompatActivity 迁移到 WearableActivity 时 我收到崩溃消息 并显示以下消息 引起原因 java lang IllegalStateException 找不到可穿戴设备 共享库类 请添加uses li
  • 对象 # 的属性“submit”不是函数

    谁能向我解释这个错误意味着什么 如果您能提供任何帮助 我将非常感激
  • log4j:ERROR setFile(null,false) 调用失败

    我面临一些奇怪的错误 如下所示 log4j ERROR setFile null false call failed java io FileNotFoundException debug log Access is denied src
  • TCL:execegrep“子进程异常退出”

    我的egrep命令有问题 当我在 tcsh 中执行命令时 它工作正常 但是当我从 tcl 脚本或在 tclsh 中执行它时 我得到 子进程异常退出 grep 使用其退出状态来指示存在 不存在匹配项 man page 如果没有匹配 则退出状态
  • 为什么使用 boost::copy_exception 时会丢失类型信息?

    当我使用boost copy exception将异常复制到exception ptr 我丢失了类型信息 看一下下面的代码 try throw std runtime error something catch exception e pt
  • 在 .NET Core 中的 MVC 之外使用 Razor

    我想在我用 NET Core 编写的 NET 控制台应用程序中使用 Razor 作为模板引擎 我遇到的独立 Razor 引擎 RazorEngine RazorTemplates 都需要完整的 NET 我正在寻找适用于 NET Core 的
  • Python 3 中“python -m SimpleHTTPServer”的等价物是什么

    Python 3 相当于什么python m SimpleHTTPServer From the docs The SimpleHTTPServer模块已合并到http server在Python 3 0中 将源文件转换为 3 0 时 2t
  • 是否可以在 JavaFX 中制作对角列标题?

    我的 JavaFX TableView 看起来像这样 如果顶部的标签是diagonal以节省空间 我想象它是这样的 目标是使该列与内容紧密贴合 尽管标题标签很长 能做到吗 None
  • Haskell 中的基本 I/O 性能

    另一个微基准测试 为什么是这个 循环 用ghc O2 fllvm 7 4 1 Linux 64位3 2内核 重定向到 dev null mapM print 1 100000000 比普通的简单 for 循环慢大约 5 倍C with wr
  • 为什么 Python 中的整数需要三倍的内存?

    在 64 位系统上 Python 中的整数占用 24 个字节 这是例如所需内存的 3 倍 C 表示 64 位整数 现在 我知道这是因为 Python 整数是对象 但是额外的内存有什么用呢 我有我的猜测 但很高兴能确定 请记住 Pythoni
  • GroupBy 从 IEnumerable 对象列表中删除重复项

    我有一个重复名称列表 我想获取没有重复名称的列表 CSVCategories from line in File ReadAllLines path Skip 1 let columns line Split select new Cate
  • LiveData 阻止在开始观察时接收最后一个值

    是否可以预防LiveData开始观察时收到最后一个值 我正在考虑使用LiveData作为事件 例如 显示消息 导航事件或对话框触发器等事件 类似于EventBus 与之间的通信相关的问题ViewModel和片段 谷歌给了我们LiveData
  • 涉及 OR 条件的高级索引 (pgsql)

    我开始更好地掌握 PostgreSQL 索引 但我遇到了 OR 条件的问题 我不知道如何优化索引以实现更快的查询 我有 6 个条件 当单独运行时 它们的成本似乎很小 以下是修剪查询的示例 包括查询计划计算时间 注意 为了降低复杂性 我没有输