Mat*_*ins 4 postgresql indexing union
我开始对PostgreSQL索引有了更好的把握,但我遇到了OR条件的问题,我不知道如何优化我的索引以获得更快的查询.
我有6个条件,当单独运行时,似乎成本很低.以下是修剪查询的示例,包括查询计划计算时间.
(注:我没有输出低于降低复杂起见,这些查询的实际查询计划,但它们都使用nested loop left joins,并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)
Run Code Online (Sandbox Code Playgroud)
我的问题是我想与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;
Run Code Online (Sandbox Code Playgroud)
不幸的是,这导致查询计划的大量增加,这似乎不再使用我的索引(相反,选择执行hash left join而不是a 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)
Run Code Online (Sandbox Code Playgroud)
关于OR-ed条件的索引,我是否应该知道哪些特殊内容可以改善我的最终查询?
更新:如果我为每个单独的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)
Run Code Online (Sandbox Code Playgroud)
根据条件,逻辑上不可能使用任何索引来帮助使用OR表达式来处理复杂条件.
像MySQL,PostgreSQL 8.0和更早版本在他们的索引文档中说:
请注意,查询或数据操作命令每个表最多只能使用一个索引.
使用PostgreSQL 8.1,这已经改变了.
但是,如果这没有帮助,您可以使用UNION您尝试的解决方案(这是MySQL用户的常见解决方案,它继续具有每个表一个索引的限制).
您应该能够对UNION查询的结果进行排序,但必须使用括号来指定ORDER BY适用于结果的括号UNION,而不仅仅是链中的最后一个子查询.
(SELECT ... )
UNION
(SELECT ... )
UNION
(SELECT ... )
ORDER BY columnname;
Run Code Online (Sandbox Code Playgroud)
我希望这有帮助; 我不是PostgreSQL优化器的专家.您可以尝试搜索邮件列表存档,或在IRC频道上询问.
| 归档时间: |
|
| 查看次数: |
1105 次 |
| 最近记录: |