如何以秒分辨率存储源数据
How to store data where source is in seconds resolution
我有一些只有第二分辨率的金融报价数据。数据本身是按时间顺序排列的。
Date Time Bid Ask
06/07/2015 19:09:29 0.7623 0.76262
06/07/2015 19:09:29 0.7623 0.76271
06/07/2015 19:09:29 0.7623 0.76276
我想做一些需要我能够知道亚二阶的分析。所以我最初的想法是 "fake" 毫秒。当同一秒内有多个滴答声(数据点)时,我假设它们在那一秒内均匀分布。因此,由于同一秒内有 3 个刻度,我假设第一个发生在第二个开始时,第二个发生在 .333,第三个发生在 .666。
两个问题。
这种方法(伪造毫秒)是存储
实际订单?
我有相当大量的数据要导入,所以我想我会在上传原始数据的两个阶段过程中进行操作,然后插入到我的目的地 table select 进行毫秒计算。因此,如果您对下面的 query/approach 有任何帮助,我们将不胜感激。
CREATE TEMPORARY TABLE dataload (
id serial
, dt date
, tm time
, bid numeric(10,5)
, ask numeric(10,5)
);
COPY dataload (dt, tm, bid, ask) FROM '/path/to/data.csv' WITH CSV HEADER;
-- INSERT INTO actual_table
SELECT
dt
, tm
, (dt||tm)::timestamp -- Need to hack the milliseconds here
from dataload
group by dt, tm;
如果您无法获得改进的数据,最好以与其背后的现实相匹配的方式对其进行建模。
所以,添加假秒可能不是一个好主意,因为你会掩盖真实情况。
相反,您可以在一秒钟内添加一个包含订单排名的字段。这可以通过 row_number() over (partition by date, time)
.
轻松完成
如果有助于减小数据大小,您始终可以将该数字转换为秒的一部分。
我通常不喜欢伪造数据。准确存储您提供的内容并使用第二列来指示排序会更准确。这将花费一些额外的存储空间,但没有混淆可能会弥补这一点。
除非你有充分的理由,否则我也不会将时间与日期分开存储。
最好使用 file_fdw 而不是中间 table,以避免额外的复制步骤。问题是 file_fdw 没有给你行号或任何其他排序方式来允许你使用 row_number() 来创建亚秒级排序。所以我们需要用到一个函数。
CREATE TABLE tick(
tick_timestamp timestamptz NOT NULL
, tick_sequence smallint NOT NULL
, CONSTRAINT tick__pk_tick_timestamp__tick_sequence PRIMARY KEY( tick_timestamp, tick_sequence )
, bid numeric(10,5) NOT NULL
, ask numeric(10,5) NOT NULL
);
CREATE FOREIGN TABLE tick_csv( tick_date date, tick_time time, bid numeric, ask numeric ) ...;
CREATE FUNCTION get_tick() RETURNS SETOF tick_csv LANGUAGE sql AS $$SELECT * FROM tick_csv$$;
COMMENT ON FUNCTION get_tick() IS $$This function is necessary because file_fdw provides no means of obtaining row numbers, which we need for safe ordering. This function allows use of WITH ORDINALITY to get a row number.$$;
INSERT INTO tick( tick_timestamp, tick_sequence, bid, ask )
SELECT tick_timestamp
-- Generate a series that resets for each second
, row_number() OVER( PARTITION BY tick_timestamp ORDER BY ordinality )
, bid
, ask
FROM (
SELECT *, ( tick_date + tick_time ) AT TIME ZONE 'America/New_York' AS tick_timestamp -- CHANGE TO CORRECT TIMEZONE
FROM get_ticks() WITH ordinality
) raw
;
您可能想省略功能位并使用类似临时序列的东西来生成行号。问题是它不能防止计划者创建一个重新排序外部 table 输出的计划。这不应该发生在只进行顺序扫描的简单操作中,但是如果您决定加入其他一些 table ,那么您很容易得到乱序的行。 SQL 函数之所以安全是因为它不会是 inlined,因为我们使用的是 WITH ORDINALITY(并且因为它没有定义为 STABLE,您可能会这样做)。
我有一些只有第二分辨率的金融报价数据。数据本身是按时间顺序排列的。
Date Time Bid Ask
06/07/2015 19:09:29 0.7623 0.76262
06/07/2015 19:09:29 0.7623 0.76271
06/07/2015 19:09:29 0.7623 0.76276
我想做一些需要我能够知道亚二阶的分析。所以我最初的想法是 "fake" 毫秒。当同一秒内有多个滴答声(数据点)时,我假设它们在那一秒内均匀分布。因此,由于同一秒内有 3 个刻度,我假设第一个发生在第二个开始时,第二个发生在 .333,第三个发生在 .666。
两个问题。
这种方法(伪造毫秒)是存储 实际订单?
我有相当大量的数据要导入,所以我想我会在上传原始数据的两个阶段过程中进行操作,然后插入到我的目的地 table select 进行毫秒计算。因此,如果您对下面的 query/approach 有任何帮助,我们将不胜感激。
CREATE TEMPORARY TABLE dataload (
id serial
, dt date
, tm time
, bid numeric(10,5)
, ask numeric(10,5)
);
COPY dataload (dt, tm, bid, ask) FROM '/path/to/data.csv' WITH CSV HEADER;
-- INSERT INTO actual_table
SELECT
dt
, tm
, (dt||tm)::timestamp -- Need to hack the milliseconds here
from dataload
group by dt, tm;
如果您无法获得改进的数据,最好以与其背后的现实相匹配的方式对其进行建模。
所以,添加假秒可能不是一个好主意,因为你会掩盖真实情况。
相反,您可以在一秒钟内添加一个包含订单排名的字段。这可以通过 row_number() over (partition by date, time)
.
如果有助于减小数据大小,您始终可以将该数字转换为秒的一部分。
我通常不喜欢伪造数据。准确存储您提供的内容并使用第二列来指示排序会更准确。这将花费一些额外的存储空间,但没有混淆可能会弥补这一点。
除非你有充分的理由,否则我也不会将时间与日期分开存储。
最好使用 file_fdw 而不是中间 table,以避免额外的复制步骤。问题是 file_fdw 没有给你行号或任何其他排序方式来允许你使用 row_number() 来创建亚秒级排序。所以我们需要用到一个函数。
CREATE TABLE tick(
tick_timestamp timestamptz NOT NULL
, tick_sequence smallint NOT NULL
, CONSTRAINT tick__pk_tick_timestamp__tick_sequence PRIMARY KEY( tick_timestamp, tick_sequence )
, bid numeric(10,5) NOT NULL
, ask numeric(10,5) NOT NULL
);
CREATE FOREIGN TABLE tick_csv( tick_date date, tick_time time, bid numeric, ask numeric ) ...;
CREATE FUNCTION get_tick() RETURNS SETOF tick_csv LANGUAGE sql AS $$SELECT * FROM tick_csv$$;
COMMENT ON FUNCTION get_tick() IS $$This function is necessary because file_fdw provides no means of obtaining row numbers, which we need for safe ordering. This function allows use of WITH ORDINALITY to get a row number.$$;
INSERT INTO tick( tick_timestamp, tick_sequence, bid, ask )
SELECT tick_timestamp
-- Generate a series that resets for each second
, row_number() OVER( PARTITION BY tick_timestamp ORDER BY ordinality )
, bid
, ask
FROM (
SELECT *, ( tick_date + tick_time ) AT TIME ZONE 'America/New_York' AS tick_timestamp -- CHANGE TO CORRECT TIMEZONE
FROM get_ticks() WITH ordinality
) raw
;
您可能想省略功能位并使用类似临时序列的东西来生成行号。问题是它不能防止计划者创建一个重新排序外部 table 输出的计划。这不应该发生在只进行顺序扫描的简单操作中,但是如果您决定加入其他一些 table ,那么您很容易得到乱序的行。 SQL 函数之所以安全是因为它不会是 inlined,因为我们使用的是 WITH ORDINALITY(并且因为它没有定义为 STABLE,您可能会这样做)。