【发布时间】:2014-11-04 13:42:54
【问题描述】:
我的最终目标是使用索引优化我的查询,但我无法添加正确的索引。我尝试过的所有方法在解释图中的成本都相同,并且没有迹象表明它甚至使用了任何索引。
我有两张桌子:
-
event有两个date列:start_date和end_date(可以为 null)。 -
fiscal_date具有:- 两个
date列start_date和end_date(不能为空) -
fiscal_year类型为char(4)的列 -
fiscal_quarter类型为char(1)的列
- 两个
还有另一个表address,它只是与event 中的外键一对一的关系。除了公钥之外,没有任何索引。
我有一个无法更改的查询,用于确定事件开始的财政季度和年份:
SELECT
e.*,
(select 'Q' || fd.fiscal_quarter || ' FY' || fd.fiscal_year
from fiscal_date fd
where e.start_date between fd.start_date and fd.end_date
limit 1) as fiscal_quarter_year,
(select 'Q' || fd.fiscal_quarter
from fiscal_date fd
where e.start_date between fd.start_date and fd.end_date
limit 1) as fiscal_quarter,
(select 'FY' || fd.fiscal_year
from fiscal_date fd
where e.start_date between fd.start_date and fd.end_date
limit 1) as fiscal_year,
a.street1, a.street2, a.street3, a.city, a.state, a.country, a.postal_code
FROM event AS e
LEFT OUTER JOIN address a ON e.address_id=a.address_id;
这是查询的解释(注意左侧所有昂贵的 seq 扫描):
根据要求,这是explain analyze 的输出:
Hash Left Join (cost=115.78..2846.64 rows=1649 width=5087) (actual time=18.334..134.279 rows=1649 loops=1)
Hash Cond: (e.address_id = a.address_id)
-> Seq Scan on event e (cost=0.00..323.49 rows=1649 width=5031) (actual time=0.223..19.808 rows=1649 loops=1)
-> Hash (cost=68.68..68.68 rows=3768 width=60) (actual time=17.797..17.797 rows=3768 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 248kB
-> Seq Scan on address a (cost=0.00..68.68 rows=3768 width=60) (actual time=0.004..9.071 rows=3768 loops=1)
SubPlan 1
-> Limit (cost=0.00..0.49 rows=1 width=28) (actual time=0.011..0.014 rows=1 loops=1649)
-> Seq Scan on fiscal_date fd (cost=0.00..1.46 rows=3 width=28) (actual time=0.006..0.006 rows=1 loops=1649)
Filter: (($0 >= start_date) AND ($0 <= end_date))
SubPlan 2
-> Limit (cost=0.00..0.48 rows=1 width=8) (actual time=0.010..0.012 rows=1 loops=1649)
-> Seq Scan on fiscal_date fd (cost=0.00..1.43 rows=3 width=8) (actual time=0.006..0.006 rows=1 loops=1649)
Filter: (($1 >= start_date) AND ($1 <= end_date))
SubPlan 3
-> Limit (cost=0.00..0.48 rows=1 width=20) (actual time=0.010..0.012 rows=1 loops=1649)
-> Seq Scan on fiscal_date fd (cost=0.00..1.43 rows=3 width=20) (actual time=0.005..0.005 rows=1 loops=1649)
Filter: (($2 >= start_date) AND ($2 <= end_date))
Total runtime: 138.008 ms
我尝试将索引添加到 event 以索引开始日期和结束日期(以及单独),将索引添加到 fiscal_date 的日期列,但似乎没有什么能减少此查询的成本计算.
我该如何优化这个查询,还是不可能?
【问题讨论】:
-
请贴出explain analyze
的输出,从提供的信息很难得出很多结论。一般提示是尽可能在子查询上使用连接,它通常执行得更好。 -
很酷的解释,这是什么原因?这是什么意思?有没有你遗漏的查询?您显示的查询从事件中选择所有行,因此索引无济于事。
-
也许只有我一个人,但我发现
explain analyze的纯文本输出更多比图形显示更能提供信息(也更容易理解) -
@amphetamachine 你的查询有问题——你使用
limit没有order by,所以PostgreSQL 可以返回它碰巧首先找到的任何匹配行。 -
@amphetamachine 同意这与优化不是特别相关。我只是指出问题所在。顺便说一句,我对人们无法更改查询、无法更新 PostgreSQL、无法安装任何东西、无法访问 Internet 并且想要一个神奇的修复,实际上并没有改变任何东西。如果你在这样的环境中,我很同情你。
标签: postgresql date indexing