mysql优化

时间:2010-11-21 16:49:51

标签: mysql optimization

我有一个包含400多个事件的'事件'表,其中包含以下关系 - 一对多有event_dates(45,000行),一对多有event_categories(1,000行)。

我会很感激所有建议,重新改进这个冗长而缓慢的查询(我的sql技能很差):

SELECT 
    events.id AS id, 
    events.name AS event, 
    events.listing_type AS TYPE , 
    GROUP_CONCAT( DISTINCT event_categories.category_id ) AS category_id,                 
    events.location AS location, 
    events.summary AS summary, 
    counties.name AS county, 
    events.postcode AS postcode, 
    events.picture AS picture, 
    events.venue AS venue, 
    events.lat AS lat, 
    events.lng AS lng
FROM 
    EVENTS , 
    event_dates, 
    event_categories, 
    counties, 
    categories
WHERE 
    events.preview =0
AND event_dates.start_date > DATE( NOW( ) )
AND events.id = event_dates.event_id
AND events.id = event_categories.event_id
AND events.county_id = counties.id
AND event_categories.category_id = categories.id
AND events.city LIKE '%London%'
GROUP BY id
ORDER BY events.id DESC

编辑: 这是个 事件搜索查询,它需要按类别表和日期表进行搜索。表结构如下:

event_dates:id start_date end_date start_time end_time event_id

event_categories:id event_id category_id

3 个答案:

答案 0 :(得分:3)

我将您的查询重写为:

  SELECT e.id, 
         e.name AS event, 
         e.listing_type AS TYPE , 
         ec.category_id,                 
         e.location,
         e.summary, 
         co.name AS county, 
         e.postcode, 
         e.picture, 
         e.venue, 
         e.lat, 
         e.lng 
    FROM EVENTS e
    JOIN EVENT_DATES ed ON ed.event_id = e.id
    JOIN (SELECT t.event_id,
                 GROUP_CONCAT( DISTINCT t.category_id ) AS category_id
            FROM EVENT_CATEGORIES t
        GROUP BY t.event_id) ec ON ec.event_id = e.id
    JOIN COUNTIES co ON c.id = e.county_id 
   WHERE e.preview = 0
     AND ed.start_date > DATE( NOW( ) )
     AND e.city LIKE '%London%'
ORDER BY e.id DESC

你有:

  • 加入CATEGORIES表,但未使用
  • 虽然OP中的GROUP BY在MySQL上有效,但这个版本是SQL标准
  • 如果EVENTS.city上有一个通配符,则左侧使用通配符LIKE搜索将无法使用索引(IE:'%London%')

建议/推荐

  • 索引连接条件列(如果它们尚不存在),然后查看索引WHERE子句中的列

答案 1 :(得分:2)

我认为你应该在更小的范围内进行GROUP_CONCAT操作(作为FROM子句中的子查询),这可能会提高整体性能。因此,也会从查询中删除表categories,因为它除了混淆之外没有任何贡献(除非您的表处于语义不完整状态,以至于您在event_categories中没有出现类别ID值定义类别表)。

这些观察结果导致:

SELECT e.id AS id,
       e.name AS event,
       e.listing_type AS type,
       cat.category_id AS category_id,
       e.location AS location,
       e.summary AS summary,
       counties.name AS county,
       e.postcode AS postcode,
       e.picture AS picture,
       e.venue AS venue,
       e.lat AS lat,
       e.lng AS lng
  FROM Events AS e
  JOIN event_dates AS d ON e.id = d.id AND d.start_date > DATE(NOW())
  JOIN (SELECT id, GROUP_CONCAT(category_id) AS category_id
          FROM event_categories
         GROUP BY id
       ) AS cat ON e.id = cat.id
  JOIN counties ON e.county_id = counties.id
 WHERE e.preview = 0
   AND e.city LIKE '%London%'
 ORDER BY events.id DESC

如果您确实需要查询中的类别表,那么它属于子查询:

SELECT e.id AS id,
       e.name AS event,
       e.listing_type AS type,
       cat.category_id AS category_id,
       e.location AS location,
       e.summary AS summary,
       counties.name AS county,
       e.postcode AS postcode,
       e.picture AS picture,
       e.venue AS venue,
       e.lat AS lat,
       e.lng AS lng
  FROM Events AS e
  JOIN event_dates AS d ON e.id = d.id AND d.start_date > DATE(NOW())
  JOIN (SELECT id, GROUP_CONCAT(category_id) AS category_id
          FROM event_categories AS ec
          JOIN categories AS ct ON ec.category_id = ct.category_id
         GROUP BY id
       ) AS cat ON e.id = cat.id
  JOIN counties ON e.county_id = counties.id
 WHERE e.preview = 0
   AND e.city LIKE '%London%'
 ORDER BY events.id DESC

答案 2 :(得分:0)

首先,摆脱AND events.city LIKE '%London%'并使您的位置定位依赖于county_id(我希望是外键)