我有一个mysql查询,这需要花费大量时间用于大约10.4毫秒的记录。这花费了很多时间

时间:2016-12-28 12:26:40

标签: mysql sql query-optimization

SELECT ticker.ticker_id,
       ticker.ticker_code,
       inter_day_ticker_candle_price_history.close AS previousDayClose
FROM inter_day_ticker_candle_price_history
INNER JOIN
  (SELECT MAX(inter_day_ticker_candle_price_history.candle_price_history_id) AS candle_price_history_id
   FROM inter_day_ticker_candle_price_history
   WHERE inter_day_ticker_candle_price_history.close>0
   GROUP BY inter_day_ticker_candle_price_history.ticker_id) derivedTable 
   ON inter_day_ticker_candle_price_history.candle_price_history_id = derivedTable.candle_price_history_id
RIGHT JOIN ticker ON ticker.ticker_id = inter_day_ticker_candle_price_history.ticker_id
WHERE ticker.is_active = 1

请建议我使用其他任何技术,我可以在这里申请减少时间。

这是表结构

Field                    Type           Null    Key     Default  Extra           
-----------------------  -------------  ------  ------  -------  ----------------
candle_price_history_id  int(8)         NO      PRI     (NULL)   auto_increment  
ticker_id                bigint(11)     NO      MUL     (NULL)                   
candle_interval          int(11)        YES             1                        
trade_date               datetime       YES             (NULL)                   
trade_price              decimal(16,2)  YES             (NULL)                   
trade_size               decimal(30,2)  YES             (NULL)                   
open                     decimal(16,2)  YES             (NULL)                   
high                     decimal(16,2)  YES             (NULL)                   
low                      decimal(16,2)  YES             (NULL)                   
close                    decimal(16,2)  YES             (NULL)                   
volume                   bigint(30)     YES             (NULL)                   
creation_date            datetime       YES             (NULL)                   
is_ebabled               bit(1)         YES             b'1'  

3 个答案:

答案 0 :(得分:1)

首先从股票行情表中选择,然后找到最新的历史条目,然后加入:

SELECT 
  t.ticker_id,
  t.ticker_code,
  h.close  AS previousDayClose 
FROM ticker t
LEFT JOIN
(
  SELECT ticker_id, MAX(candle_price_history_id) AS candle_price_history_id
  FROM inter_day_ticker_candle_price_history
  WHERE close > 0
  GROUP BY ticker_id
) m on m.ticker_id = t.ticker_id
LEFT JOIN inter_day_ticker_candle_price_history h 
  ON h.candle_price_history_id = m.candle_price_history_id
WHERE t.is_active = 1;

但是,您的查询也应该有效。

确保拥有适当的索引。我建议:

create index idx_ticker on ticker(is_active, 
                                  ticker_id, 
                                  ticker_code);

create index idx_history on inter_day_ticker_candle_price_history(ticker_id,
                                                                  close,
                                                                  candle_price_history_id);

create index idx_history on inter_day_ticker_candle_price_history(close,
                                                                  ticker_id,
                                                                  candle_price_history_id);

(列的顺序可能有所不同,因此您可能希望尝试两个版本的历史索引。当然,您可以使用不同的名称同时创建两个索引并查看使用哪个索引。)

答案 1 :(得分:0)

通常创建适当的索引会加快查询的倍数过滤条件。

例如,在 ticker_id 上创建索引可能是提高查询速度的关键。

另一方面,在 close is_active 上创建索引可能会有所帮助,但只有 is_active = 1 时才能达到10%或更少,表中的记录。

此外,您可以更改 ORDER BY candle_price_history_id DESC LIMIT 1 的MAX功能,因为该表已按 candle_price_history_id

排序

答案 2 :(得分:0)

这似乎是一个“groupwise max”问题。有关该模式的优化技术,请参阅http://mysql.rjweb.org/doc.php/groupwise_max

请参阅我关于缩小表格大小的评论。我认为这可能是一个巨大的表,可能比RAM更大?

如果这是InnoDB,innodb_buffer_pool_size需要大约70%的可用RAM。

如果(ticker_id, tradedate)是唯一的,则将其设为PRIMARY KEY并完全摆脱id。顺序很重要 - 这会将给定股票代码的所有行聚集在一起,从而减少I / O. (如果您当前受I / O限制,此可能为您提供10倍的加速。)

提供EXPLAIN SELECT ...。您需要使用派生查询对 start 进行查询(如所写)。 LEFT JOIN不允许这样做。

考虑删除关闭< = 0。

的非活动行和行