我对PostgreSQL 8.3运行了相当长而复杂的SQL查询。部分查询涉及对今天结束的日期范围进行过滤,如下所示:
where ...
and sp1.price_date between current_date::date - '1 year'::interval and current_date::date
and sp4.price_date between current_date::date - '2 weeks'::interval and current_date::date
and sp5.price_date = (select sp6.price_date
from stock_prices sp6
where sp6.stock_id = s.stock_id
and sp6.price_date < current_date::date
order by sp6.price_date desc
limit 1)
...
此查询需要大约5分钟才能运行(第一次),第二次大约需要1.5分钟。通过查看EXPLAIN ANALYZE输出,似乎 current_date 是问题所在。所以我尝试用硬编码的日期替换它,如下所示:
where ...
and sp1.price_date between '2009-09-30'::date - '1 year'::interval and '2009-09-30'::date
and sp4.price_date between '2009-09-30'::date - '2 weeks'::interval and '2009-09-30'::date
and sp5.price_date = (select sp6.price_date
from stock_prices sp6
where sp6.stock_id = s.stock_id
and sp6.price_date < '2009-09-30'::date
order by sp6.price_date desc
limit 1)
...
然后查询运行半秒钟!这很好,除了日期在查询中总共有10个位置,当然,我不希望用户必须在10个地方手动更改它。在MS SQL Server中,我只是声明一个具有当前日期值的变量并使用它,但apparently在Postgres中的普通SQL中是不可能的。
如何在自动使用当前日期的同时快速运行此查询?
答案 0 :(得分:2)
首先,在两个变体上发布EXPLAIN ANALYZE,以便我们看到。第一步,弄清楚为什么一个比另一个慢。查看整个查询也可能很有用。
第一个变体应该是可优化的。
如果没有让您的用户在多个地方更改您的查询,请考虑撰写stored procedure,或者在优化第一个变体时,/ view。
编辑:注意到你的current__date - '...':: interval会返回一个没有时区的时间戳。我假设您想要转换为日期:(current_date - '2周':: interval):: date
答案 1 :(得分:1)
编辑:以下测试但是它比原始查询运行得更慢! 关于这一点的教训可能是所有类型转换(:: date,:: interval等)都会导致性能损失。也许这些显式的强制转换可以某种方式被其他东西取代,并且还可以预先计算一些表达式,例如'D.RightNow :: date - '1 year':: interval'。
- 原始回复 -
您可以将当前日期插入另一个空表中并加入该表...
换句话说,假设创建了这样一个表并命名为tblNow,那么带有与日期相关的过滤器的查询可能会变成这样:
UPDATE tblNow SET RightNow = TIMEOFDAY();
-- note: above could use CURRENT_DATE or whatever date function matches the
-- semantics of the date fields in other tables.
-- and now the original query can become
from ...
join tblNow AS D ON 1=1 -- added join
-- then all current_date::date below changed to D.RightNow
where ...
and sp1.price_date between D.RightNow::date - '1 year'::interval and D.RightNow::date
and sp4.price_date between D.RightNow::date - '2 weeks'::interval and D.RightNow::date
and sp5.price_date = (select sp6.price_date
from stock_prices sp6
where sp6.stock_id = s.stock_id
and sp6.price_date < D.RightNow::date
order by sp6.price_date desc
limit 1)
...
每次我们希望在当前时刻运行它时,有效地要求 no 编辑查询。我不熟悉postgreSQL,但这种方法对于在SELECT语句中使用变量的任何限制都是一种自然的解决方法。