0

我正在尝试编写一个 postgresql 查询来计算金融烛台数据的“ Aroon Indicator ”。我在同一数据集上对其他技术分析指标的所有其他尝试都运行得很快,但此查询运行时间为 50 秒。我认为必须有一些我缺少的效率。

简而言之,“阿隆指标”是“根据特定证券或指数达到近期高点以来的时间长度计算的”。

因此,对于 25 天的期限,公式为 ((25 - (number_of_days_since_the_high_price_in_last_25 天) / 25) * 100。

这是我写的查询似乎有效,但速度很慢:

WITH crypto_w_row_num AS (
    SELECT 
        *,
        ROW_NUMBER() OVER(PARTITION BY symbol, granularity ORDER BY period DESC) as row_num
    FROM crypto
)
SELECT 
    c1.*,
    c2.price_high,
    ((25 - (c1.row_num - c2.row_num)) / 25.0) * 100 AS aroon_bullish,
    ((25 - (c1.row_num - c3.row_num)) / 25.0) * 100 AS aroon_bearish
FROM crypto_w_row_num c1
LEFT JOIN LATERAL (
    SELECT * 
    FROM crypto_w_row_num 
    WHERE row_num > c1.row_num - 25 AND row_num <= c1.row_num
    AND symbol = c1.symbol AND granularity = c1.granularity
    ORDER BY price_high DESC, period DESC
    LIMIT 1
) c2 ON TRUE
LEFT JOIN LATERAL (
    SELECT * 
    FROM crypto_w_row_num 
    WHERE row_num > c1.row_num - 25 AND row_num <= c1.row_num
    AND symbol = c1.symbol AND granularity = c1.granularity
    ORDER BY price_high ASC, period DESC
    LIMIT 1
) c3 ON TRUE
WHERE c1.symbol = 'SHIB-USD' AND c1.granularity = '300' ORDER BY c1.period;

在我探索索引策略以加快速度之前,是否有一些根本不同的方法可以解决这个问题?

表 DDL:

CREATE TABLE crypto (
    period timestamp without time zone,
    symbol character varying,
    granularity character varying,
    price_low numeric,
    price_high numeric,
    price_open numeric,
    price_close numeric,
    volume numeric,
    CONSTRAINT crypto_pkey PRIMARY KEY (period, symbol, granularity)
);

数据示例:

INSERT INTO "public"."crypto"("period","symbol","granularity","price_low","price_high","price_open","price_close","volume")
VALUES
(E'2021-09-09 11:10:00',E'SHIB-USD',E'300',0.00001,0.00001399,0.00001,0.00001399,2593611248),
(E'2021-09-09 11:15:00',E'SHIB-USD',E'300',0.0000081,0.00003111,0.000013,0.00000955,25317710205),
(E'2021-09-09 11:20:00',E'SHIB-USD',E'300',0.000006,0.00001,0.0000095,0.0000072,30067341828),
(E'2021-09-09 11:25:00',E'SHIB-USD',E'300',0.00000601,0.00000797,0.0000072,0.00000748,21321324571),
(E'2021-09-09 11:30:00',E'SHIB-USD',E'300',0.00000738,0.00000748,0.00000747,0.00000744,16398559934),
(E'2021-09-09 11:35:00',E'SHIB-USD',E'300',0.00000725,0.00000776,0.00000746,0.00000734,34220044532),
(E'2021-09-09 11:40:00',E'SHIB-USD',E'300',0.0000073,0.0000074,0.00000732,0.00000737,21881556898),
(E'2021-09-09 11:45:00',E'SHIB-USD',E'300',0.00000736,0.00000748,0.00000737,0.00000747,13908049922),
(E'2021-09-09 11:50:00',E'SHIB-USD',E'300',0.00000746,0.0000155,0.00000747,0.0000123,54739385481),
(E'2021-09-09 11:55:00',E'SHIB-USD',E'300',0.0000099,0.0000155,0.000013,0.000013,67925125159),
(E'2021-09-09 12:00:00',E'SHIB-USD',E'300',0.00001152,0.0000579,0.00001277,0.00005,91181753605),
(E'2021-09-09 12:05:00',E'SHIB-USD',E'300',0.00003,0.00007499,0.000055,0.00003588,70897539508),
(E'2021-09-09 12:10:00',E'SHIB-USD',E'300',0.000032,0.00005,0.000035,0.00004222,67743029887),
(E'2021-09-09 12:15:00',E'SHIB-USD',E'300',0.000035,0.0000429,0.000042,0.000035,47572071936),
(E'2021-09-09 12:20:00',E'SHIB-USD',E'300',0.0000206,0.00003799,0.000035,0.00003499,54289742296),
(E'2021-09-09 12:25:00',E'SHIB-USD',E'300',0.000027,0.000035,0.00003498,0.00002701,37194821296),
(E'2021-09-09 12:30:00',E'SHIB-USD',E'300',0.000025,0.00003799,0.00002701,0.00003798,42206077664),
(E'2021-09-09 12:35:00',E'SHIB-USD',E'300',0.00003442,0.000045,0.00003442,0.00004201,51968895955),
(E'2021-09-09 12:40:00',E'SHIB-USD',E'300',0.00003481,0.00004512,0.00004202,0.00003781,36145026338),
(E'2021-09-09 12:45:00',E'SHIB-USD',E'300',0.000037,0.00005718,0.00003732,0.000056,62897590107),
(E'2021-09-09 12:50:00',E'SHIB-USD',E'300',0.00005,0.0000578,0.000055,0.00005047,49399828385),
(E'2021-09-09 12:55:00',E'SHIB-USD',E'300',0.000041,0.0000548,0.00005,0.0000509,48604886186),
(E'2021-09-09 13:00:00',E'SHIB-USD',E'300',0.000048,0.00006,0.00005,0.00005801,43411455146),
(E'2021-09-09 13:05:00',E'SHIB-USD',E'300',0.00005804,0.00009,0.00005991,0.00006985,86353267664),
(E'2021-09-09 13:10:00',E'SHIB-USD',E'300',0.0000671,0.000085,0.00006983,0.00007713,51822852940),
(E'2021-09-09 13:15:00',E'SHIB-USD',E'300',0.00006455,0.00008148,0.000076,0.00007542,46955190713),
(E'2021-09-09 13:20:00',E'SHIB-USD',E'300',0.0000699,0.0000785,0.00007542,0.000073,30770645915),
(E'2021-09-09 13:25:00',E'SHIB-USD',E'300',0.00006514,0.000073,0.00007296,0.000066,12935376159),
(E'2021-09-09 13:30:00',E'SHIB-USD',E'300',0.00005004,0.000066,0.00006541,0.00005012,24877546170),
(E'2021-09-09 13:35:00',E'SHIB-USD',E'300',0.00005,0.00005808,0.00005029,0.00005807,20687029957);

提前致谢!

4

1 回答 1

0

查询的每个部分都取决于 CTE crypto_w_row_num,除了最后一个where子句。这可能会消除主查询所做的大部分工作。如果将其where移入 CTE 并在连接之前尽可能多地消除会发生什么。您可以explain analyze在每个版本上运行,然后查看它们是否产生相同的结果。诚然,只有 38 行,所有这些都满足标准,很难做出很好的判断,但我跑了两个都解释了。你的原版运行时间4.69ms,修改版1.97ms。结果看起来是一样的,但这只是一个快速浏览。

with crypto_w_row_num as (
    select 
        *,
        row_number() over(partition by symbol, granularity order by period desc) as row_num
    from crypto
where symbol = 'SHIB-USD' and granularity = '300' order by period    
)
select 
    c1.*,
    c2.price_high,
    ((25 - (c1.row_num - c2.row_num)) / 25.0) * 100 as aroon_bullish,
    ((25 - (c1.row_num - c3.row_num)) / 25.0) * 100 as aroon_bearish
from crypto_w_row_num c1
left join lateral (
    select * 
    from crypto_w_row_num 
    where row_num > c1.row_num - 25 and row_num <= c1.row_num
    and symbol = c1.symbol and granularity = c1.granularity
    order by price_high desc, period desc
    limit 1
) c2 on true
left join lateral (
    select * 
    from crypto_w_row_num 
    where row_num > c1.row_num - 25 and row_num <= c1.row_num
    and symbol = c1.symbol and granularity = c1.granularity
    order by price_high asc, period desc
    limit 1
) c3 on true
;

使用索引似乎不太可能有帮助,并且您已经有一个包含直接查询的唯一列的索引,可能会更改顺序:

CONSTRAINT crypto_pkey PRIMARY KEY(symbol, granularity,period )

此外,除非您确实需要结果中的所有列,否则不要select *只列出所需的列。随着大型结果集的内存管理开始发挥作用 - 需要的时间越多。

于 2021-10-16T20:55:02.243 回答