我有一张比特币交易表:
CREATE TABLE `transactions` ( `trans_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `trans_exchange` int(10) unsigned DEFAULT NULL, `trans_currency_base` int(10) unsigned DEFAULT NULL, `trans_currency_counter` int(10) unsigned DEFAULT NULL, `trans_tid` varchar(20) DEFAULT NULL, `trans_type` tinyint(4) DEFAULT NULL, `trans_price` decimal(15,4) DEFAULT NULL, `trans_amount` decimal(15,8) DEFAULT NULL, `trans_datetime` datetime DEFAULT NULL, `trans_sid` bigint(20) DEFAULT NULL, `trans_timestamp` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`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`) ) ENGINE=MyISAM AUTO_INCREMENT=6162559 DEFAULT CHARSET=utf8;
从 AUTO_INCRMENT 值可以看出,该表有超过 600 万条条目。最终还会有更多。
我想查询该表以获得任意时间间隔内的最高价格、最低价格、交易量和交易总额。为了实现这一点,我使用如下查询:
SELECT DATE_FORMAT( MIN(transactions.trans_datetime), '%Y/%m/%d %H:%i:00' ) AS trans_datetime, SUM(transactions.trans_amount) as trans_volume, MAX(transactions.trans_price) as trans_max_price, MIN(transactions.trans_price) as trans_min_price, COUNT(transactions.trans_id) AS trans_count FROM transactions WHERE transactions.trans_datetime BETWEEN '2014-09-14 00:00:00' AND '2015-09-13 23:59:00' GROUP BY 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 Using where; Using temporary; Using filesort
问题:是否可以更好地优化它?这种结构或方法有缺陷吗?我尝试了几种方法,但只成功地获得了微弱的毫秒级增益。
最佳答案
表中的大部分数据都是过去 12 个月的数据?那么你需要触摸 table 的大部分吗?那么就没有办法加快查询速度。但是,您可以更快地获得相同数量级的输出...
创建汇总表。它将有一个DATE
作为PRIMARY KEY
,并且这些列将实际上是SELECT
中提到的字段。
一旦您最初填充了汇总表,就可以通过每晚为当天的事务添加新行来维护它。 More in my blog .
然后,获取所需输出的查询将命中此汇总表(只有几百行),而不是具有数百万行或行的表。
关于MySQL:SUM/MAX/MIN GROUP BY 查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32581606/