我有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)
解决方法
像MysqL,Postgresql 8.0和更早版本的docs on indexes:
Note that a query or data manipulation command can use at most one index per table.
但是,如果这没有帮助,您可以使用您尝试的UNION解决方案(这是MysqL用户的常见解决方案,它继续具有每个表一个索引的限制).
您应该能够对UNION查询的结果进行排序,但必须使用括号来指定ORDER BY应用于UNION的结果,而不仅仅是链中的最后一个子查询.
(SELECT ... ) UNION (SELECT ... ) UNION (SELECT ... ) ORDER BY columnname;
我希望这有帮助;我不是Postgresql优化器的专家.您可以尝试搜索mailing list archives,或询问IRC channel.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。