【问题标题】:Optimize Postgresql Function Fiscal Month Date优化 Postgresql 函数财月日期
【发布时间】:2013-09-09 13:15:34
【问题描述】:

我编写了下面的函数,它与下表结合使用,存储公司的会计月份定义,但是当用于按会计月份聚合数据时,这个函数似乎相当慢。谁能指点我如何加快速度?

编辑:我仍然有这个功能的一些瓶颈。我已经重写它以消除一些绒毛,但它仍然比在我的查询中加入财政月表要慢得多。但是我还是宁愿使用一个函数来方便使用,这样我就不必重写几十个仍在使用它的查询。

创建或替换函数 get_fiscal_month(date) 返回整数 AS $身体$ 选择案例 当提取(年从 1 美元)= 开始日期和 1 美元

编辑:2014 年 5 月 6 日(重写功能稍快)

CREATE OR REPLACE FUNCTION get_fiscal_month(date)
    RETURNS integer AS
    $BODY$
    SELECT month FROM fiscal_months WHERE $1 >= start_date AND $1 <= end_date
    $BODY$
LANGUAGE sql STABLE
COST 1000;

变化
1. 删除日期为 2. 去掉 WHERE (EXTRACT YEAR FROM date) = year(这是一个不必要的步骤)
3. 将 VOLATILE 更改为 STABLE
4. 成本从100改为1000

创建表财政_月 ( id 序列号 NOT NULL, 年份整数 NOT NULL, 月份整数 NOT NULL, start_date 日期不为空, end_date 日期不为空, CONSTRAINT accounting_months_pkey PRIMARY KEY (id), CONSTRAINT accounting_months_ukey UNIQUE(年、月) )

CREATE TABLE fiscal_months
(
id serial NOT NULL,
year integer NOT NULL,
month integer NOT NULL,
start_date date NOT NULL,
end_date date NOT NULL,
CONSTRAINT fiscal_months_pkey PRIMARY KEY (id),
CONSTRAINT fiscal_months_ukey UNIQUE (year, month),
CONSTRAINT fiscal_months_ukey_end UNIQUE (end_date),
CONSTRAINT fiscal_months_ukey_start UNIQUE (start_date)
)

CREATE INDEX fiscal_months_index_bothdates
    ON fiscal_months USING btree (start_date, end_date);

CREATE INDEX fiscal_months_index_test2
    ON fiscal_months USING btree (start_date);

变化
1. 在下方添加了来自 SO 用户的每个 cmets 的索引。

表格统计
顺序扫描 48018264
顺序元组读取 4006572336
索引扫描 3251027 获取的索引元组 27236663
已插入元组 0
元组更新 0
元组已删除 0
元组 HOT 更新 0
活元组 86
死元组 0
堆块读取 3047
堆块命中 51266249
索引块读取 13
索引块命中 3251026 吐司块阅读
吐司块命中
Toast 索引块读取
Toast 索引块命中
上次真空 2014-05-05 16:46:54.087489-05
上次自动真空
最后分析 2014-05-06 13:23:47.709653-05
上次自动分析 2014-05-05 16:47:29.248862-05
表大小 8192 字节
吐司桌尺寸 无
索引大小 96 kB

示例数据
年 月 Start_Date End_Date
---- ----- ---------- ---------
2014 1 "2014-01-01" "2014-01-24"
2014 2 《2014-01-25》 《2014-02-21》
2014 3 《2014-02-22》 《2014-03-28》
2014 4 《2014-03-29》 《2014-04-25》
2014 5 《2014-04-26》 《2014-05-23》
2014 年 6 《2014 年 5 月 24 日》《2014 年 6 月 27 日》

附言我正在使用 Postgresql 8.3
p.s.我正在使用 Postgresql 8.4

【问题讨论】:

  • start_dateend_date 字段添加唯一索引。
  • else 子句中的 select 语句是减慢此功能的罪魁祸首...您需要将语句更改为单个 select 而不是像这里那样的两个。
  • @Twelfth:你怎么知道?顺便说一句,我不怀疑你,但我想学习。
  • 我会使用两个单独的唯一索引。
  • 查询中选择行内的选择语句永远不会很好地执行,您基本上会为通过此的每条记录发生第二次查询。 2 个查询很少(几乎永远不会)胜过 1 个查询。

标签: sql postgresql sql-function


【解决方案1】:

该参考表中有哪些数据?会计月份通常可以从某个日期确定,而无需查询。

例如,如果您的 2012 财年从 2012 年 4 月到 2013 年 3 月,您可以通过以下方式确定当前财月:

to_char(date_trunc('month',current_date) - interval '3' month, 'YYYY MM')

我会考虑以这种方式实现算法,最好是在 SQL 中(当然还有你使用 CASE,因为看起来财政月份的逻辑在 2009 年发生了变化)。

【讨论】:

  • 我编辑/更新了我的帖子以显示一些示例数据。我不确定我是否可以像您建议的那样即时计算。
【解决方案2】:

我编写了下面的函数,它与下表结合使用,存储公司的会计月份定义,但是当用于按会计月份聚合数据时,这个函数似乎相当慢。谁能指点我如何加快速度?

我认为您的问题在于您如何使用此功能。如果您以这种方式聚合数据,您就是在拒绝计划者使用 finance_month() 加入的能力。

IMO 你应该做的是在聚合查询的 UNION 部分中调用财政月()仅当data &gt;= '2008-01-01'。将它封装在一个函数中意味着它可能不是可内联的,因此您不能执行哈希连接,而是坚持使用嵌套循环,这几乎肯定是您的问题所在。

【讨论】:

  • 请看我上面修改过的帖子,我添加了更多细节。
  • 是的,我正在使用这个函数进行聚合。例如。 SELECT get_fiscal_month(mydate) AS m, COUNT(*) AS v FROM sometablewithadate GROUP BY m ORDER BY m
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
  • 1970-01-01
  • 2011-11-06
相关资源
最近更新 更多