是否有比在无限制前进和当前行之间行驶更快的方式?'

时间:2017-02-06 15:57:49

标签: sql postgresql postgresql-performance

我有以下数据库表:

date        a   b   c   d   add result
23.02.07    A   B   C1  D1  1   1
24.02.07    A   B   C1  D1  0   1
25.02.07    A   B   C1  D1  1   2
26.02.07    A   B   C1  D1  1   3
27.02.07    A   B   C1  D1  1   4
28.02.07    A   B   C1  D1  0   4
01.03.07    A   B   C1  D1  0   4
02.03.07    A   B   C1  D1  0   4
03.03.07    A   B   C1  D1  1   5
04.03.07    A   B   C1  D1  0   5
05.03.07    A   B   C1  D1  0   5
06.03.07    A   B   C1  D1  0   5
07.03.07    A   B   C1  D1  2   7

17.02.07    A   B   C2  D2  1   1
18.02.07    A   B   C2  D2  0   1
19.02.07    A   B   C2  D2  0   1
20.02.07    A   B   C2  D2  0   1
21.02.07    A   B   C2  D2  0   1
22.02.07    A   B   C2  D2  0   1
23.02.07    A   B   C2  D2  0   1
24.02.07    A   B   C2  D2  0   1
25.02.07    A   B   C2  D2  1   2
26.02.07    A   B   C2  D2  3   5
27.02.07    A   B   C2  D2  1   6
28.02.07    A   B   C2  D2  0   6

列结果(最后一个)不是实际数据集的一部分。本专栏展示了我想要实现的目标。 基本上我是summin'以前的所有值"添加"通过使用如下的分析函数来确定给定分区的当前分区:

SUM(add) OVER(PARTITION BY
    A,
    B,
    C,
    D,
    ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS result

这种方法有效,但在查询大量数据时速度很慢。

更多见解:

  • 日期有一个btree索引(不是日期数据类型,但字符不同)。
  • 所有其他字符都是变化的,而不是add是一个整数。
  • A和B也有btree索引。

有更好/更高效的方法吗?

1 个答案:

答案 0 :(得分:0)

窗口框架定义

您的ORDER BY不具有确定性(多个行的每个分区具有相同的date)。使用框架定义 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,您的查询结果可以在不同的调用之间进行更改。

Read the definitions in the manual carefully.

默认框架定义为 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,这可能对您的情况更有意义:它会按排序顺序添加当前行的所有对等项(当天)在分区中),因此在同一天分区中的所有行都得到相同的总数。

使排序顺序具有确定性(例如,通过将PK添加为最后ORDER BY项)或切换到RANGE。由于RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW是默认值,因此您可以简化:

SUM(add) OVER(PARTITION BY A, B, C, D ORDER BY date)

正确date处理

这是不对的:

  

日期有一个btree索引(不是日期数据类型,但字符不同)。

这是一个带来后果的错误。永远不要将日期存储为varchar,将日期存储为date。即使ORDER BY date发生以正确使用您的特定字符串格式(&#39; 23.02.07&#39; ,就像您在问题中所做的那样< strong> ),它仍然较慢。而且容易出错。存储空间更大(同样也更慢)。

性能优化

除此之外,具有匹配顺序的索引列的多列索引可以提高性能(like Thorsten commented):

CREATE INDEX foo ON tbl (A, B, C, D, date, add);

您可以使用此索引对物理表进行聚类,以获得更快的结果:

详细信息取决于完整情况:Postgres版本,表格定义,完整查询,......