我有一个大表,用于存储我的Web应用程序的调试信息。问题是该表现在是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`)
)
如果有任何想法获得相同的结果而没有一个非常棒的文件排序!
答案 0 :(得分:4)
答案 1 :(得分:1)
您的关键问题是您没有指定WHERE
子句。您对WHERE 1=1
的使用毫无意义。问题是你试图从MySQL获取YEAR
和MONTH
而不限制行数,因此它在每行之前处理MONTH(..)和YEAR(...)它能够处理GROUP。
在我之前的建议之后仍然没有使用INDEX这一事实表明您的查询比您所允许的更多,如果是这种情况请告诉我,我可以更轻松地帮助您。否则,我建议在下面检查(虽然我不得不猜测你的目的,因为你没有说明你想要实现的目标)
如果您是在过去6个日历月之后,那么以下内容也会有很大帮助。
SELECT
COUNT(id) AS `count`,
MONTH(event_date) AS `month`,
YEAR(event_date) AS `year`
FROM events
-- Get the first day of this month, and subtract 6 months
WHERE event_date > SUBDATE(DATE_FORMAT(NOW(), '%Y-%m-01'), INTERVAL 6 MONTH)
GROUP BY `year` DESC, `month` DESC;
如果您有其他WHERE标准,那将改变给出的建议,如果是这样,请更新
答案 2 :(得分:0)
除了其他人发布的内容之外:
如果您运行EXPLAIN SELECT...
并且MySQL报告它不使用该查询的索引(或者不使用您想要的索引),则可以通过使用SELECT... FORCE INDEX...
查询数据来解决此问题。有关此语法的更多详细信息,请查看此处:http://dev.mysql.com/doc/refman/5.6/en/index-hints.html
答案 3 :(得分:0)
您正在使用SELECT *,这意味着选择所有行以便扫描整个表格 - 尝试选择要显示的特定行
此外,没有参数可以过滤数据,因此会读取并返回整个表格,尝试按日期或其他参数进行限制