【问题标题】:How to index a table with several ORDER BY clauses?如何索引具有多个 ORDER BY 子句的表?
【发布时间】:2013-01-09 07:50:15
【问题描述】:

我有一个 IntradayPrices1Minute 表,我在其中存储 1 分钟时间范围内股票的开盘价、最高价、最低价和收盘价:

CREATE TABLE `IntradayPrices1Minute` (
  `ticker` varchar(10) NOT NULL DEFAULT '',
  `datetime` datetime NOT NULL,
  `volume` mediumint(11) unsigned NOT NULL,
  `open` decimal(8,4) unsigned NOT NULL,
  `high` decimal(8,4) unsigned NOT NULL,
  `low` decimal(8,4) unsigned NOT NULL,
  `close` decimal(8,4) unsigned NOT NULL,
  PRIMARY KEY (`ticker`,`datetime`),
  UNIQUE KEY `indxTickerDatetime` (`ticker`,`datetime`)
)

我建立了一个查询,可以计算这些股票的每日开盘价、最高价、最低价和收盘价。这是查询:

select 
    `IntradayPrices1Minute`.`ticker` AS `ticker`,
    cast(`IntradayPrices1Minute`.`datetime` as date) AS `Date`,
    substring_index(group_concat(cast(`IntradayPrices1Minute`.`open` as char charset utf8) order by `IntradayPrices1Minute`.`datetime` ASC separator ','),',',1) AS `Daily Open`,
    max(greatest(`IntradayPrices1Minute`.`open`,`IntradayPrices1Minute`.`high`,`IntradayPrices1Minute`.`low`,`IntradayPrices1Minute`.`close`)) AS `Daily High`,
    min(least(`IntradayPrices1Minute`.`open`,`IntradayPrices1Minute`.`high`,`IntradayPrices1Minute`.`low`,`IntradayPrices1Minute`.`close`)) AS `Daily Low`,
    substring_index(group_concat(cast(`IntradayPrices1Minute`.`close` as char charset utf8) 

order by 
   `IntradayPrices1Minute`.`datetime` DESC separator ','),',',1) AS `Daily Close` 
from    
   `IntradayPrices1Minute` 

group by 
   `IntradayPrices1Minute`.`ticker`,
   cast(`IntradayPrices1Minute`.`datetime` as date)

这是我只有 4-5 天的数据时得到的部分结果(截至今天,我还有更多天的数据):

ticker  Date        Open    High    Low     Close
----    ----------  ------  ------  ------  ------ 
AAAE    2012-11-26  0.0100  0.0100  0.0100  0.0100
AAAE    2012-11-27  0.0130  0.0140  0.0083  0.0140
AAAE    2012-11-28  0.0140  0.0175  0.0140  0.0165
AAAE    2012-11-29  0.0175  0.0175  0.0137  0.0137
AAMRQ   2012-11-26  0.4411  0.5300  0.4411  0.5290
AAMRQ   2012-11-27  0.5100  0.5110  0.4610  0.4950
AAMRQ   2012-11-28  0.4820  0.4900  0.4300  0.4640
AAMRQ   2012-11-29  0.4505  0.4590  0.4411  0.4590
AAMRQ   2012-11-30  0.4500  0.4570  0.4455  0.4568

所以截至今天,IntradayPrices1Minute 表已经有 9625952 条记录,并且增长了大约。每天350000条记录

使用 LIMIT 1000 执行之前的 SELECT 已经花费了超过 8 秒,所以我发现需要一些索引,但是我对索引以及如何决定它们的知识非常有限。

我认为一些信息可能对你们这些更专业的人有用:

show indexes from IntradayPrices1Minute

返回:

IntradayPrices1Minute   0   PRIMARY 1   ticker  A   32368               BTREE       
IntradayPrices1Minute   0   PRIMARY 2   datetime    A   9872508             BTREE       
IntradayPrices1Minute   0   indxTickerDatetime  1   ticker  A   21793               BTREE       
IntradayPrices1Minute   0   indxTickerDatetime  2   datetime    A   9872508             BTREE       

show profiling 命令显示:

Status                 Duration
------                 --------
starting               0.000055
checking permission    0.000003
Opening tables         0.000018
System lock            0.000005
init                   0.000022
optimizing             0.000004
statistics             0.000011
preparing              0.000006
executing              0.000027
Sorting result         8.533655
Sending data           0.233446
end                    0.000010
removing tmp table     0.000006
end                    0.000007
removing tmp table     0.000002
end                    0.000005
query end              0.000003
closing tables         0.000004
freeing items          0.000041
logging slow query     0.000002
cleaning up            0.000003

不幸的是,由于我的知识有限,这些信息对我没有多大用处。我怀疑所有这些 ORDER BY 可能是如此密集的,因为显示分析指出使用了 8.53 秒“排序结果”,但我不知道如何处理以提高查询效率。

非常感谢您提出的任何建议,特别是如果它可以帮助我更好地理解为将来可能还需要排除故障的查询建立索引。

干杯, 博加

【问题讨论】:

    标签: mysql indexing sql-order-by


    【解决方案1】:

    尝试改变

    GROUP BY ticker, date(datetime)
    

    进入

    GROUP BY ticker, datetime
    

    第一个不使用您的索引,因此需要(非常慢)文件排序。二是使用索引,速度更快。

    您可以使用以下方法找到此类问题:

    EXPLAIN SELECT * FROM table
    

    【讨论】:

    • 我很抱歉...我发布了旧版本的查询。我已经使用生产中的实际查询编辑了我的原始帖子,现在您可以看到查询确实按索引的 2 个字段分组。所以我不知道为什么超过 8 秒的排序:-(
    • 答案还是一样。您没有使用索引(如使用 EXPLAIN 选项所见),因为您投射了“日期时间”字段。这将起作用并且速度更快:group by IntradayPrices1Minute.ticker, IntradayPrices1Minute.datetime
    • 谢谢。你完全正确!我不记得为什么我首先要在日期进行 CAST。无论如何,它现在非常快;-)
    • 无视:现在我记得为什么我有 CAST 迄今为止。这是因为我需要按日期分组,而不是按日期时间分组。我现在意识到做你建议的事情会给我错误的结果:-(
    • 无论如何,我想我会改变表格的结构,让日期和时间在不同的列中,所以没关系
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    • 2021-07-20
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    相关资源
    最近更新 更多