postgresql – 涉及OR-ed条件的高级索引(pgsql)
我开始对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:
使用PostgreSQL 8.1,它有changed. 但是,如果这没有帮助,您可以使用您尝试的UNION解决方案(这是MySQL用户的常见解决方案,它继续具有每个表一个索引的限制). 您应该能够对UNION查询的结果进行排序,但必须使用括号来指定ORDER BY应用于UNION的结果,而不仅仅是链中的最后一个子查询. (SELECT ... ) UNION (SELECT ... ) UNION (SELECT ... ) ORDER BY columnname; 我希望这有帮助;我不是PostgreSQL优化器的专家.您可以尝试搜索mailing list archives,或询问IRC channel. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |