加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgresql – 涉及OR-ed条件的高级索引(pgsql)

发布时间:2020-12-13 16:00:32 所属栏目:百科 来源:网络整理
导读:我开始对PostgreSQL索引有了更好的把握,但我遇到了OR条件的问题,我不知道如何优化我的索引以获得更快的查询. 我有6个条件,当单独运行时,似乎成本很低.以下是修剪查询的示例,包括查询计划计算时间. (注意:为了降低复杂性,我没有为下面的这些查询输出实际的查
我开始对PostgreSQL索引有了更好的把握,但我遇到了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)
 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.*,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.*,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.*,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;

不幸的是,这导致查询计划的大量增加,这似乎不再使用我的索引(相反,选择执行散列左连接而不是嵌套循环左连接,并对先前使用的索引执行各种序列扫描扫描).

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

关于OR-ed条件的索引,我是否应该知道哪些特殊内容可以改善我的最终查询?

更新:如果我为每个单独的SELECT使用UNION,这似乎加快了查询速度.但是,如果我将来选择,这会阻止我订购我的结果吗?这是我通过UNION加速查询所做的工作:

EXPLAIN ANALYZE
SELECT t1.*,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.*,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.*,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.*,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.*,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.*,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和更早版本的docs on indexes:

Note that a query or data manipulation command can use at most one index per table.

使用PostgreSQL 8.1,它有changed.

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

您应该能够对UNION查询的结果进行排序,但必须使用括号来指定ORDER BY应用于UNION的结果,而不仅仅是链中的最后一个子查询.

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

我希望这有帮助;我不是PostgreSQL优化器的专家.您可以尝试搜索mailing list archives,或询问IRC channel.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读