Mysql 插入/更新SMA的查询速度(简单移动平均)

Mysql 插入/更新SMA的查询速度(简单移动平均),mysql,sql,date,sql-update,query-optimization,Mysql,Sql,Date,Sql Update,Query Optimization,我想在我的表中包含一列股票数据的简单移动平均值。我已经成功地创建了几个查询,但是查询速度很慢。我的目标是提高查询速度 我有下表: CREATE TABLE `timeseries_test` ( `timeseries_id` int(11) NOT NULL AUTO_INCREMENT, `stock_id` int(10) NOT NULL, `date` date NOT NULL, `open` decimal(16,8) NOT NULL, `high` decimal(1

我想在我的表中包含一列股票数据的简单移动平均值。我已经成功地创建了几个查询,但是查询速度很慢。我的目标是提高查询速度

我有下表:

CREATE TABLE `timeseries_test` (
 `timeseries_id` int(11) NOT NULL AUTO_INCREMENT,
 `stock_id` int(10) NOT NULL,
 `date` date NOT NULL,
 `open` decimal(16,8) NOT NULL,
 `high` decimal(16,8) NOT NULL,
 `low` decimal(16,8) NOT NULL,
 `close` decimal(16,8) NOT NULL,
 `adjusted_close` double(16,8) NOT NULL,
 `volume` int(16) NOT NULL,
 `dividend` double(16,8) NOT NULL,
 `split_coefficient` double(16,15) NOT NULL,
 `100sma` decimal(16,8) NOT NULL,
 PRIMARY KEY (`timeseries_id`),
 KEY `stock` (`stock_id`),
 KEY `date` (`date`),
 KEY `date_stock` (`stock_id`,`date`)
) ENGINE=InnoDB AUTO_INCREMENT=5444325 DEFAULT CHARSET=latin1
我尝试过许多不同的查询格式,但每5000行都需要25秒。select查询只需不到一秒钟的时间。下面是一个查询示例:

UPDATE stock.timeseries_test t1 INNER JOIN (
SELECT a.timeseries_id,
       Round( ( SELECT SUM(b.close) / COUNT(b.close)
                FROM timeseries_test AS b
                WHERE DATEDIFF(a.date, b.date) BETWEEN 0 AND 99 AND a.stock_id = b.stock_id
              ), 2 ) AS '100sma'
     FROM timeseries_test AS a) t2

ON t1.`timeseries_id` = t2.`timeseries_id`
SET t1.100sma = t2.100SMA
WHERE t2.100sma = null
在解释查询下面:

1   PRIMARY <derived2>  NULL    ALL NULL    NULL    NULL    NULL    10385   10.00   Using where 
1   UPDATE  t1  NULL    eq_ref  PRIMARY PRIMARY 4   t2.timeseries_id    1   100.00  NULL    
2   DERIVED a   NULL    index   NULL    date_stock  7   NULL    10385   100.00  Using index 
3   DEPENDENT SUBQUERY  b   NULL    ref stock,date_stock    stock   4   stock.a.stock_id    5192    100.00  Using where 
1主NULL所有NULL 10385 10.00使用where
1更新t1 NULL eq_ref PRIMARY 4 t2.timeseries_id 1 100.00 NULL
2使用索引导出空索引空日期\u股票7空10385 100.00
3依赖子查询b NULL ref stock,date_stock 4 stock.a.stock_id 5192 100.00使用where

感谢您的帮助

如果您运行的是MySQL 8.0,我建议窗口函数使用
范围
规范;这就是对相关子查询的需要

update stock.timeseries_test t1 
inner join (
    select timeseries_id,
    avg(close) over(
        partition by stock_id 
        order by date 
        range between interval 99 day preceding and current row
    ) `100sma`
    from timeseries_test
) t2 on t1.timeseries_id = t2.timeseries_id
set t1.`100sma` = t2.`100sma`
不清楚原始的外部
where
子句的目的是什么,所以我删除了它:

WHERE t2.`100sma` = null
如果确实要检查
null
ness,则需要
为null
;但这样做几乎会破坏
update
语句的整个逻辑。也许你的意思是:

WHERE t1.`100sma` is null

函数是不可搜索的。而不是

DATEDIFF(a.date, b.date) BETWEEN 0 AND 99
使用

(或者应该交换
a
b

我怀疑(从列名来看)这对(
stock\u id
date
)是唯一的,
timeseries\u id
从未真正使用过。如果这些是正确的,那么

PRIMARY KEY (`timeseries_id`),
KEY `date_stock` (`stock_id`,`date`)
-->

需要将ON(timestamp_id)上的
更改为测试这两列

另外,由于还有另一个索引以相同的列开头,所以请忽略此项:


感谢您的反馈。不过,我正在运行MySQL 5.7.2。如果我没有找到替代解决方案,我会尝试。
PRIMARY KEY (`timeseries_id`),
KEY `date_stock` (`stock_id`,`date`)
PRIMARY KEY(`stock_id`,`date`)
KEY `stock` (`stock_id`),