У меня есть таблица Bitcoin сделок:MySQL: SUM/MAX/MIN GROUP BY запроса оптимизации
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_INCREMENT, таблица имеет более 6 миллионов словарных статей. В конечном итоге их будет гораздо больше.
Я хотел бы запросить таблицу, чтобы получить максимальную цену, минимальную цену, объем и общую сумму, торгуемую в течение произвольных временных интервалов. Для достижения этой цели, я использую запрос, как это:
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
Это следует выбирать сделки, совершенные в течение года, сгруппированных по день (86400 секунд).
Идея - это поле метки времени, которое содержит то же значение, что и дата и время, но как временную метку ... Я нашел это быстрее, чем 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
Вопрос: возможно оптимизировать это лучше? Является ли эта структура или подход ошибочной? Я попробовал несколько подходов и добился успеха лишь в миллисекундах.
Почему транзакции.trans_datetime как аргумент для агрегатной функции, так и в предложении GROUP BY? – jarlh
Как и в целом, вы должны GROUP BY тем же, что и SELECT. Итак, если вы выбрали DATE_FORMAT, тогда GROUP BY DATE_FORMAT. Это правда, что вам это не нужно, но это не приведет к ошибкам. – Strawberry
Бит DATE_FORMAT не предназначен для группировки; это было только там, поэтому с каждой группой появляется некоторое представление времени, так что оно может быть построено на графике. Извлечение его из SQL-запроса, по-видимому, не влияет на скорость. – suzerain