我在优化查询时遇到问题,可以使用一些帮助。我正在系统中拉入事件,必须连接其他几个表,以确保事件应该显示等等...查询运行顺利(大约480ms),直到我在混合中引入另一个表。查询如下:
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秒。任何帮助将不胜感激。
答案 0 :(得分: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 的表格。这意味着它必须从这些表中读取每个行,并与其他表中的行进行比较。您可以通过将行列中的值相乘来了解它正在做多少工作。基本上,它正在进行数十亿行比较以解决连接问题。随着表格的增长,这个查询会变得更糟。
使用LEFT [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有时为null)。
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
没问题,因为它已经在进行主键查找。