MySQL 对 GROUP BY YEAR 和 GROUP BY YEAR 进行文件排序月
我有一个大表来存储我的网络应用程序的调试信息。问题是该表现在有 500,000 行,并且其中一个查询速度很慢,因为未使用索引。
SQL:
EXPLAIN SELECT count(*) AS `count`, month(event_date) AS `month`, year(event_date) AS `year`FROM events WHERE 1 = 1 GROUP BY year(event_date) DESC, month(event_date) DESC LIMIT 6;
结果:
SIMPLE events index NULL event_date 8 NULL 139358 Using index; Using temporary; Using file sort
这是表结构。
CREATE TABLE IF NOT EXISTS `events` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Event Primary Key',
`event_number` int(11) NOT NULL,
`user_id` int(11) unsigned NOT NULL COMMENT 'User ID',
`server_id` int(11) unsigned DEFAULT NULL COMMENT 'The ID of the remote log client',
`remote_id` int(11) unsigned DEFAULT NULL COMMENT 'The Event Primary Key from the remote client',
`event_date` datetime NOT NULL COMMENT 'Event Datetime in local timezone',
`event_date_utc` datetime NOT NULL COMMENT 'Event Datetime in UTC timezone',
`event_type` varchar(255) NOT NULL COMMENT 'The type of event',
`event_source` varchar(255) NOT NULL COMMENT 'Text description of the source of the event',
`event_severity` varchar(255) NOT NULL COMMENT 'Notice, Warning etc',
`event_file` text NOT NULL COMMENT 'The full file location of the source of the event',
`event_file_line` int(11) NOT NULL COMMENT 'The line in the file that triggered the event',
`event_ip_address` varchar(255) NOT NULL COMMENT 'IP Address of the user that triggered the event',
`event_summary` varchar(255) NOT NULL COMMENT 'A summary of the description',
`event_description` text NOT NULL COMMENT 'Full description of the event',
`event_trace` text NOT NULL COMMENT 'Full PHP trace',
`event_synced` int(1) unsigned DEFAULT '0',
PRIMARY KEY (`id`),
KEY `event_type` (`event_type`),
KEY `event_source` (`event_source`),
KEY `user_id` (`user_id`),
KEY `server_id` (`server_id`),
KEY `event_date` (`event_date`)
)
如果有人有任何想法可以在不进行文件排序的情况下获得相同的结果,那就太棒了!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
GROUP BY 意味着 MySQL 中的 ORDER BY
因此,请尝试添加 ORDER BY NULL:这通常会消除文件排序
请参阅 "ORDER BY Optimization"
GROUP BY implies ORDER BY in MySQL
So try adding ORDER BY NULL: this usually eliminates a filesort
See "ORDER BY Optimization" in the MySQL docs
您的关键问题是您没有指定
WHERE
子句。您使用WHERE 1=1
是毫无意义的。问题是您试图从 MySQL 获取YEAR
和MONTH
而不限制行数,因此它处理 MONTH(..) 和 YEAR(.. .) 在能够处理 GROUP 之前对每一行进行处理。事实上,在我之前的建议之后,它仍然没有使用 INDEX,这表明您的查询比您所透露的更多,如果是这种情况,请告诉我,我可以更轻松地帮助您。否则,我建议您检查以下内容(尽管我不得不猜测您的目的,因为您没有说明您想要实现的目标)
如果您是在过去 6 个日历月之后,那么以下内容也会有很大帮助。
如果您有其他 WHERE 标准,这将更改给出的建议,因此如果是这种情况,请更新
Your key problem is that you are specifying no
WHERE
clause. Your use ofWHERE 1=1
is pointless. The problem is that you are trying to get theYEAR
andMONTH
from MySQL without limiting the number of rows, and therefore it processes MONTH(..) and YEAR(...) for each row before it is able to process the GROUP.The fact it still isn't using the INDEX after my earlier suggestion indicates you have more to your query than you are letting on, if that's the case please let me know and I can help you more easily. Otherwise, I would recommend checking below (though I'm having to guess at your purposes as you haven't stated what you are trying to achieve)
If you are after the last 6 calendar months specifically then the following would also help significantly.
If you have additional WHERE criteria though, that would change the advice given so if that's the case please update
除了其他人发布的内容之外:
如果您运行
EXPLAIN SELECT...
并且 MySQL 报告它对该查询没有使用索引(或者不是您想要的索引),您可以通过以下方式解决此问题使用SELECT...FORCE INDEX...
查询数据。有关其语法的更多详细信息,请查看此处: http:// /dev.mysql.com/doc/refman/5.6/en/index-hints.htmlIn addition to what the others have posted:
If you run an
EXPLAIN SELECT...
and MySQL reports that it uses no index for that query (or not the one you want), you could solve this by querying the data withSELECT... FORCE INDEX...
. For more details about the syntax of this, look here: http://dev.mysql.com/doc/refman/5.6/en/index-hints.html您正在使用 SELECT *,这意味着选择所有行,以便扫描整个表 - 尝试选择要显示的特定行
此外,没有参数来过滤数据,因此读取并返回整个表,尝试按日期或其他参数进行限制
You are using SELECT * which means select all rows so the whole table is scanned - try selecting specific rows to show
Also there are no parameters to filter the data so the whole table is read and returned, try restricting either by date or some other parameter