我有以下两个表
CREATE TABLE IF NOT EXISTS `events` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM;
CREATE TABLE IF NOT EXISTS `events_dates` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`event_id` bigint(20) NOT NULL,
`date` date NOT NULL,
`start_time` time NOT NULL,
`end_time` time NOT NULL,
PRIMARY KEY (`id`),
KEY `event_id` (`event_id`),
KEY `date` (`event_id`)
) ENGINE=MyISAM;
链接是event_id的地方
我想要的是检索所有唯一的事件记录及其各自的事件日期,这些事件日期按特定时间段内递增的最小日期排序
基本上,以下查询完全符合我的要求
SELECT Event.id, Event.title, EventDate.date, EventDate.start_time, EventDate.end_time
FROM
events AS Event
JOIN
com_events_dates AS EventDate
ON (Event.id = EventDate.event_id AND EventDate.date = (
SELECT MIN(MinEventDate.date) FROM events_dates AS MinEventDate
WHERE MinEventDate.event_id = Event.id AND MinEventDate.date >= CURDATE() # AND `MinEventDate`.`date` < '2013-02-27'
)
)
WHERE
EventDate.date >= CURDATE() # AND `EventDate`.`date` < '2013-02-27'
ORDER BY EventDate.date ASC , EventDate.start_time ASC , EventDate.end_time DESC
LIMIT 20
当我想使用group by和其他子查询时,此查询是多次尝试进一步改善最初的慢速时间(1.5秒)的结果。它是最快的但是考虑到总共有1400个事件记录和10000个事件记录,查询需要400多毫秒的时间来处理,我也会根据这个(为了寻呼目的)运行计数,这需要花费大量的时间。好。 奇怪的是,在main where子句中省略了EventDate条件会导致它更高1s +。
我可以采取哪些措施来改善这种情况或在表格结构中使用不同的方法吗?
答案 0 :(得分:0)
如果您正在讨论优化,那么在可能的情况下包含执行计划会很有帮助。
顺便试试这个(如果你还没试过的话):
SELECT
Event.id,
Event.title,
EventDate.date,
EventDate.start_time,
EventDate.end_time
FROM
(select e.id, e.title, min(date) as MinDate
from events_dates as ed
join events as e on e.id = ed.event_id
where date >= CURDATE() and date < '2013-02-27'
group by e.id, e.title) as Event
JOIN events_dates AS EventDate ON Event.id = EventDate.event_id
and Event.MinDate = EventDate.date
ORDER BY EventDate.date ASC , EventDate.start_time ASC , EventDate.end_time DESC
LIMIT 20
;
#assuming event_dates.date for greater event_dates.id always greater
SELECT
Event.id,
Event.title,
EventDate.date,
EventDate.start_time,
EventDate.end_time
FROM
(select e.id, e.title, min(ed.id) as MinID
from events_dates as ed
join events as e on e.id = ed.event_id
where date >= CURDATE() and date < '2013-02-27'
group by e.id, e.title) as Event
JOIN events_dates AS EventDate ON Event.id = EventDate.event_id
and Event.MinID = EventDate.id
ORDER BY EventDate.date ASC , EventDate.start_time ASC , EventDate.end_time DESC
LIMIT 20
答案 1 :(得分:0)
只是向其他人澄清...... MySQL中的“#”充当延续评论,在查询中基本上被忽略,它不是“AND EventDate.Date&lt;'2013-02-27'” 。也就是说,您似乎想要一个尚未发生的所有事件的列表。我将从一个简单的“预查询”开始,它只是根据尚未发生的事件日期来抓取所有事件和最小日期。然后将该结果连接到其他表以获取您想要的其余字段
SELECT
E.ID,
E.Title,
ED2.`date`,
ED2.Start_Time,
ED2.End_Time
FROM
( SELECT
ED.Event_ID,
MIN( ED.`date` ) as MinEventDate
from
Event_Dates ED
where
ED.`date` >= curdate()
group by
ED.Event_ID ) PreQuery
JOIN Events E
ON PreQuery.Event_ID = E.ID
JOIN Event_Dates ED2
ON PreQuery.Event_ID = ED2.Event_ID
AND PreQuery.MinEventDate = ED2.`date`
ORDER BY
ED2.`date`,
ED2.Start_Time,
ED2.End_Time DESC
LIMIT 20
您的表在事件ID上有多余的索引,只是名称不同。调用索引date
的名称并不意味着要被索引的列。 parens(event_id
)中的值是构建索引的值。
所以,我会将你的创建表改为......
KEY `date` ( `event_id`, `date`, `start_time` )
或者,手动创建索引。
Create index ByEventAndDate on Event_Dates ( `event_id`, `date`, `start_time` )