【发布时间】: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