【发布时间】:2021-09-13 09:49:51
【问题描述】:
我有一个名为holdings_all 的表,它有超过 65m 行,每天都会在上面插入新行,其中一列是trade_type,它的值将取决于比较
SharesOwned 在今天的DateAdded-Fund-Ticker 和DateAdded-Fund-Ticker 的前一天之间,可能的值是:
- 如果今天的
SharesOwned等于前一天的SharesOwned那么Trade_Type= 0。 - 如果今天的
SharesOwned小于前一天的SharesOwned那么Trade_Type= 1。 - 如果今天的
SharesOwned大于前一天的SharesOwned那么Trade_Type= 2。 - 如果今天的
SharesOwned在前一天不存在,那么Trade_Type= 3。 - 如果今天的
SharesOwned不存在但前一天存在,则Trade_Type= 4。
为了让思考更快并避免行损坏,我采用了这种方法:
- 在名为
tmp_holdings_all的表中下载新行。 - 在名为
mlha的表中从holdings_all获取前一天的行。 - 最后,在
tmp_holdings_all中进行任何查询,然后将其移动到holdings_all表中。
对于类型 0、1 和 2,我会在几秒钟内得到影响并纠正行,但是对于类型 3 和 4,它需要很长时间甚至超过几个小时并且永远不会完成,我在这里做错了什么?
UPDATE tmp_holdings_all uha
JOIN (SELECT tha.id as cid,
CASE
WHEN mlha.SharesOwned = tha.SharesOwned then 0
WHEN mlha.SharesOwned > tha.SharesOwned then 1
WHEN mlha.SharesOwned < tha.SharesOwned then 2
END AS CTrade_type
FROM mlha
JOIN tmp_holdings_all tha
ON tha.fund = mlha.fund
AND tha.ticker = mlha.ticker) ttha
ON uha.id = ttha.cid
SET uha.Trade_type = ttha.CTrade_type;
Trade_type 3 和 4:
UPDATE tmp_holdings_all uha
JOIN (SELECT
ha.id as cid,
CASE
WHEN mlha.id IS NULL then 3
END AS CTrade_type
FROM mlha
RIGHT JOIN tmp_holdings_all ha
ON ha.fund = mlha.fund
AND ha.ticker = mlha.ticker
where mlha.id IS NULL) ttha
ON uha.id = ttha.cid
SET
uha.Trade_type = ttha.CTrade_type;
REPLACE INTO tmp_holdings_all(Fund,ticker,SharesOwned, Trade_Type)
SELECT
mlha.Fund, mlha.ticker, mlha.SharesOwned,
CASE
WHEN ha.id IS NULL then 4
END AS Trade_type
FROM mlha
LEFT JOIN tmp_holdings_all ha
ON ha.fund = mlha.fund
AND ha.ticker = mlha.ticker
WHERE ha.id IS NULL
holding_all表结构:
CREATE TABLE IF NOT EXISTS `tmp_holdings_all` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`DateAdded` date DEFAULT NULL,
`Fund` char(15) COLLATE utf8_bin DEFAULT NULL,
`Asset` char(96) COLLATE utf8_bin DEFAULT NULL,
`rank` int(11) DEFAULT NULL,
`Weighting` float DEFAULT NULL,
`Ticker` char(20) COLLATE utf8_bin DEFAULT NULL,
`Style` char(15) COLLATE utf8_bin DEFAULT NULL,
`FirstBought` date DEFAULT NULL,
`SharesOwned` int(11) DEFAULT NULL,
`Sector` char(45) COLLATE utf8_bin DEFAULT NULL,
`Price` float DEFAULT NULL,
`Country` char(25) COLLATE utf8_bin DEFAULT NULL,
`Currency` char(3) COLLATE utf8_bin DEFAULT NULL,
`PriceUSD` decimal(13,6) unsigned DEFAULT NULL,
`Trade_type` int(11) DEFAULT NULL,
PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1
【问题讨论】:
标签: mysql left-join query-optimization