我有一个具有以下结构的mysql表:
make runtest
并且它有超过30000000条记录。
sudo
现在的问题是它非常慢,select的结果需要很长时间才能从表中获取记录。
我的以下子查询花了将近30分钟来获取一天的记录:
mysql> show create table logs \G;
Create Table: CREATE TABLE `logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`request` text,
`response` longtext,
`msisdn` varchar(255) DEFAULT NULL,
`username` varchar(255) DEFAULT NULL,
`shortcode` varchar(255) DEFAULT NULL,
`response_code` varchar(255) DEFAULT NULL,
`response_description` text,
`transaction_name` varchar(250) DEFAULT NULL,
`system_owner` varchar(250) DEFAULT NULL,
`request_date_time` datetime DEFAULT NULL,
`response_date_time` datetime DEFAULT NULL,
`comments` text,
`user_type` varchar(255) DEFAULT NULL,
`channel` varchar(20) DEFAULT 'WEB',
/**
other columns here....
other 18 columns here, with Type varchar and Text
**/
PRIMARY KEY (`id`),
KEY `transaction_name` (`transaction_name`) USING BTREE,
KEY `msisdn` (`msisdn`) USING BTREE,
KEY `username` (`username`) USING BTREE,
KEY `request_date_time` (`request_date_time`) USING BTREE,
KEY `system_owner` (`system_owner`) USING BTREE,
KEY `shortcode` (`shortcode`) USING BTREE,
KEY `response_code` (`response_code`) USING BTREE,
KEY `channel` (`channel`) USING BTREE,
KEY `request_date_time_2` (`request_date_time`),
KEY `response_date_time` (`response_date_time`)
) ENGINE=InnoDB AUTO_INCREMENT=59582405 DEFAULT CHARSET=utf8
我还在表中添加了索引,但它仍然很慢。
有关如何加快速度的任何帮助?
修改 使用EXPLAIN
运行上述查询mysql> select count(*) from logs;
+----------+
| count(*) |
+----------+
| 38962312 |
+----------+
1 row in set (1 min 17.77 sec)
答案 0 :(得分:0)
目前,查询必须扫描整个表格。
但首先,让我们说一个可能的错误:
AND DATE(REQUEST_DATE_TIME) BETWEEN '2016-10-26 00:00:00'
AND '2016-10-27 00:00:00'
为您提供两天天的日志 - 27日的所有第26天和所有。或者那是你真正想要的吗? (BETWEEN
包含。)
但性能问题是不会使用索引,因为request_date_time
隐藏在函数内(DATE
)。
跳转到更好的方式来表达它:
AND REQUEST_DATE_TIME >= '2016-10-26'
AND REQUEST_DATE_TIME < '2016-10-26' + INTERVAL 1 DAY
DATETIME
与日期进行比较。1
更改为您想要的许多天 - 而无需处理闰日等。request_date_time
上使用索引,从而严重削减要扫描的数据量。至于其他诱人的地方:
!=
不能很好地优化,因此没有“复合”指数可能是有益的。WHERE
,因此没有索引对GROUP BY
或ORDER BY
有用。DATE()
中WHERE
的评论不适用于GROUP BY
;无需改变。为什么有子查询?我认为它可以在一个单独的层中完成。这将消除一个相当大的临时表。 (是的,它意味着TIMESTAMPDIFF()
的3次使用,但这可能比临时表便宜很多。)
多少内存? innodb_buffer_pool_size
的价值是什么?
如果我的评论不够,如果您经常运行这样的查询(超过一天或超过日期范围),那么我们可以讨论构建和维护Summary table,这可能会给你一个10倍加速。