1

我在优化查询时遇到问题,可以使用一些帮助。我目前正在一个系统中提取事件,该系统必须加入其他几个表以确保应该显示事件等......查询运行顺利(大约 480 毫秒),直到我在混合中引入另一个表。查询如下:

SELECT 
    keyword_terms, 
    `esf`.*, 
    `venue`.`name` AS venue_name, 
    ...
    `venue`.`zip`, ase.region_id, 
    (DATE(NOW()) BETWEEN...AND ase.region_id IS NULL) as featured, 
    getDistance(`venue`.`lat`, `venue`.`lng`, 36.073, -79.7903) as distance, 
    `network_exclusion`.`id` as net_exc_id
FROM (`event_search_flat` esf)
# Problematic part of query (pulling in the very next date for the event)
LEFT JOIN (
        SELECT event_id, MIN(TIMESTAMP(CONCAT(event_date.date, ' ', event_date.end_time))) AS next_date FROM event_date WHERE 
        event_date.date >= CURDATE() OR (event_date.date = CURDATE() AND TIME(event_date.end_time) >= TIME(NOW()))
        GROUP BY event_id
) edate ON edate.event_id=esf.object_id
# Pull in associated ad space
LEFT JOIN `ad_space` ads ON `ads`.`data_type`=`esf`.`data_type` AND ads.object_id=esf.object_id
# and make sure it is featured within region
LEFT JOIN `ad_space_exclusion` ase ON ase.ad_space_id=ads.id AND region_id =5
# Get venue details
LEFT JOIN `venue` ON `esf`.`venue_id`=`venue`.`id`
# Make sure this event should be listed
LEFT JOIN `network_exclusion` ON network_exclusion.data_type=esf.data_type  
                 AND network_exclusion.object_id=esf.object_id
                 AND network_exclusion.region_id=5
WHERE `esf`.`event_type` IN ('things to do') 
AND (`edate`.`next_date` >= '2013-07-18 16:23:53')
GROUP BY `esf`.`esf_id`
HAVING `net_exc_id` IS NULL
AND `distance` <= 40
ORDER BY DATE(edate.next_date) asc, 
`distance` asc
LIMIT 6

似乎问题出在 event_date 表上,但我不确定如何优化此查询(我尝试了各种视图、索引等...无济于事)。我运行 EXPLAIN 并收到以下信息:http ://cl.ly/image/3r3u1o0n2A46 。 在此处输入图像描述

目前,查询需要 6.6 秒。任何帮助将不胜感激。

4

1 回答 1

1
  • 您可以Using index通过创建复合索引来获取 event_date 子查询(event_id, date, end_time)。这可能会将子查询变成仅索引查询,这应该会稍微加快速度。

    子查询可能最好写成如下,没有GROUP BY

    SELECT event_id, TIMESTAMP(CONCAT(event_date.date, ' ', event_date.end_time))) AS next_date
    FROM event_date 
    WHERE event_date.date >= CURDATE() 
      OR (event_date.date = CURDATE() AND TIME(event_date.end_time) >= TIME(NOW()))
    ORDER BY next_date LIMIT 1
    
  • 我更担心您的 EXPLAIN 显示了这么多带有type=ALL的表。这意味着它必须从这些表中读取每一行并与其他表中的行进行比较。您可以通过将行列中的值相乘来了解它做了多少工作。基本上,它会进行数十亿行比较来解决连接问题。随着表的增长,这个查询会变得更糟。

  • UsingLEFT [OUTER] JOIN有一个特定的目的,如果你真的打算使用INNER JOIN,你应该这样做,因为在它不属于的地方使用外连接可能会破坏优化。A LEFT JOIN B仅当您希望其中的行A可能没有匹配的行时才使用外连接B

    例如,我假设基于列命名约定LEFT JOIN venue ON esf.venue_id=venue.id应该是一个内部连接,因为应该总是有一个 esf.venue_id 引用的场所(除非 esf.venue_id 有时为空)。

  • event_search_flat应该有一个复合索引,其中首先包含在 WHERE 子句中使用的列,然后是要连接到其他表的列: (event_type, object_id, data_type, event_id)

  • ad_space应该有一个用于连接的复合索引:(data_type, object_id). 这也需要内部连接吗?

  • ad_space_exclusion应该有一个用于连接的复合索引:(ad_space_id, region_id)

  • network_exclusion应该有一个用于连接的复合索引:(data_type, object_id, region_id)

  • venue没关系,因为它已经在进行主键查找了。

于 2013-07-18T21:04:05.787 回答