【问题标题】:MySQL: SUM/MAX/MIN GROUP BY query optimizeMySQL:SUM/MAX/MIN GROUP BY 查询优化
【发布时间】:2015-09-16 05:34:59
【问题描述】:

我有一张比特币交易表:

创建表`事务`( `trans_id` bigint(20) 无符号 NOT NULL AUTO_INCREMENT, `trans_exchange` int(10) 无符号默认 NULL, `trans_currency_base` int(10) 无符号默认 NULL, `trans_currency_counter` int(10) 无符号默认 NULL, `trans_tid` varchar(20) 默认为空, `trans_type` tinyint(4) 默认为 NULL, `trans_price` 十进制(15,4)默认为空, `trans_amount` 十进制(15,8)默认为空, `trans_datetime` 日期时间默认为 NULL, `trans_sid` bigint(20) 默认为空, `trans_timestamp` int(10) unsigned DEFAULT NULL, 主键(`trans_id`), KEY `trans_tid` (`trans_tid`), KEY `trans_datetime` (`trans_datetime`), KEY `trans_timestmp` (`trans_timestamp`), KEY `trans_price` (`trans_price`), KEY `trans_amount` (`trans_amount`) ) 引擎=MyISAM AUTO_INCREMENT=6162559 默认字符集=utf8;

从 AUTO_INCREMENT 值可以看出,该表有超过 600 万个条目。最终还会有更多。

我想查询表格以获取任意时间间隔内的最高价格、最低价格、交易量和总交易量。为此,我使用这样的查询:

选择 DATE_FORMAT(MIN(transactions.trans_datetime), '%Y/%m/%d %H:%i:00' ) 作为 trans_datetime, SUM(transactions.trans_amount) 作为 trans_volume, MAX(transactions.trans_price) 作为 trans_max_price, MIN(transactions.trans_price) 作为 trans_min_price, COUNT(transactions.trans_id) AS trans_count 从 交易 在哪里 transactions.trans_datetime 在“2014-09-14 00:00:00”和“2015-09-13 23:59:00”之间 通过...分组 transactions.trans_timestamp DIV 86400

这应该选择一年内进行的交易,按天(86,400 秒)分组。

想法是时间戳字段,它包含与日期时间相同的值,但作为时间戳...我发现这比 UNIX_TIMESTAMP(trans_datetime) 快,除以我希望在时间间隔内的秒数.

问题:查询很慢。我得到 4+ 秒的处理时间。这是 EXPLAIN 的结果:

id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE transactions ALL trans_datetime,trans_timestmp NULL NULL NULL 6162558 使用where;使用临时的;使用文件排序

问题: 是否可以更好地优化它?这种结构或方法有缺陷吗?我尝试了几种方法,但只成功地获得了微弱的毫秒级增益。

【问题讨论】:

  • 为什么 transactions.trans_datetime 同时作为聚合函数和 GROUP BY 子句的参数?
  • 顺便说一句,一般来说,您应该按您选择的相同事物进行分组。所以,如果你选择一个 DATE_FORMAT,那么 GROUP BY 一个 DATE_FORMAT。确实不必这样做,但不这样做很可能会导致错误。
  • DATE_FORMAT 位并不意味着被分组;它只是在那里,所以每个组都有一些时间表示,以便可以将其绘制在图表上。从 SQL 查询中完全删除它似乎对速度没有影响。

标签: mysql sql optimization group-by


【解决方案1】:

表中的大部分数据是过去 12 个月的数据?所以你需要触摸大部分桌子吗?那么就没有办法加快 查询了。但是,您可以更快地获得相同的输出数量级...

创建一个汇总表。它将有一个DATE 作为PRIMARY KEY,并且这些列实际上是您的SELECT 中提到的字段。

一旦您最初填充了汇总表,然后通过每天晚上为当天的交易添加一个新行来维护它。 More in my blog.

然后,获取所需输出的查询将访问此汇总表(只有几百行),而不是具有数百万行或行的表。

【讨论】:

  • 非常感谢。这正是我在放弃优化查询后开始研究的方法,不幸的是,这将消除我希望拥有的任意查找质量。数据跨越多年;目标是能够选择任何时间跨度,并带有一些适合数据集的自动调整“间隔”。因此,您可以查看过去 10 个月或过去 10 小时或其他任何时间的数据,系统会智能地调整间隔……也许这种灵活性在当前设置下是不可行的。
  • 一天粒度的汇总表将涵盖大多数用途。您可以切换到从事实表中获取小时分辨率,但需要注意的是,如果有人确切地要求最后 12345 小时,它会很慢(来自事实表)。鉴于,询问过去 500 天的速度会相当快(来自汇总表)。在“现实生活”中,人们不会要求 12345 小时,也不会要求去年 4 月的 3 小时。
猜你喜欢
  • 2019-08-16
  • 2015-12-10
  • 2017-11-05
  • 1970-01-01
  • 2011-08-29
  • 2012-12-31
  • 2018-10-26
  • 2018-03-09
  • 1970-01-01
相关资源
最近更新 更多