1

我有以下两张表

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 多毫秒的时间来处理,我也基于此运行计数(用于分页目的),这需要大量时间好。奇怪的是,在主 where 子句中省略 EventDate 条件会导致它甚至更高 1s+。

我可以做些什么来改进这个或表结构的不同方法吗?

4

2 回答 2

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
于 2013-02-28T01:34:32.047 回答
0

只是为了向其他人澄清...... MySQL 中的“#”充当延续注释,在查询中基本上被忽略,它不是“AND EventDate.Date < '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` )
于 2013-02-28T03:37:26.740 回答