[MySQL自联接优化,同时计算移动平均值

问题描述 投票:0回答:2

我创建了一个mysql查询,通过使用多个自联接来计算数据的移动平均值,如下所示。这很耗时,每个查询的数据行数为10万。有什么方法可以进一步优化以减少时间吗?

select a.rownum,a.ma_small_price, b.ma_medium_price from
    (SELECT t3.rownum, AVG(t.last_price) as 'ma_small_price' 
FROM temp_data t3
    left JOIN temp_data t ON t.rownum BETWEEN ifnull(t3.rownum,0) - @psmall AND t3.rownum
GROUP BY t3.rownum) 
inner join
    (SELECT t3.rownum, AVG(t.last_price) as 'ma_medium_price' 
FROM temp_data t3
    left JOIN temp_data t ON t.rownum BETWEEN ifnull(t3.rownum,0) - @pmedium AND t3.rownum
GROUP BY t3.rownum) b on a.rownum = b.rownum
mysql optimization self-join moving-average
2个回答
1
投票

由于您正在运行MySQL 8,因此您应该能够使用窗口函数来更有效地获得相同的结果。没有看到样本数据,很难100%确定,但这应该很接近。请注意,要在窗口框架中使用变量,您需要使用准备好的语句:

SET @sql = '
SELECT rownum,
       AVG(last_price) OVER (ORDER BY rownum ROWS BETWEEN ? PRECEDING AND CURRENT ROW) AS ma_small_price,
       AVG(last_price) OVER (ORDER BY rownum ROWS BETWEEN ? PRECEDING AND CURRENT ROW) AS ma_medium_price
FROM temp_data';
PREPARE stmt FROM @sql;
EXECUTE stmt USING @psmall, @pmedium;

Demo on dbfiddle


0
投票

OVER ( ... )令人失望地慢-在MySQL 8.0和MariaDB 10.x中。

我喜欢“指数移动平均线”比“移动平均线”更易于计算。以下内容大致相当于尼克提出的内容。这运行得更快,但结果略有不同:

SELECT  rownum,
        @small := @small + 0.5 * (last_price - @small) AS mae_small_price,
        @med   := @med   + 0.2 * (last_price - @med)   AS mae_med_price
    FROM ( SELECT @small := 10, @med := 10 ) AS init
    JOIN temp_data
    ORDER BY rownum;

系数控制指数移动平均值适应数据变化的速度。它应大于0且小于1。

© www.soinside.com 2019 - 2024. All rights reserved.