复杂的MySQL选择左连接优化索引

时间:2013-10-10 08:55:17

标签: mysql join left-join

我有一个非常复杂的查询正在运行,并查找加入订阅详细信息并按距离排序的成员位置。

有人可以提供有关我应该添加的正确索引和基数的指示,以加快此负载。

现在有100万条记录需要75秒,我知道它可以改进。

谢谢。

SELECT SQL_CALC_FOUND_ROWS (((acos(sin((33.987541*pi()/180)) * sin((users_data.lat*pi()/180))+cos((33.987541*pi()/180)) * cos((users_data.lat*pi()/180)) * cos(((-118.472153- users_data.lon)* pi()/180))))*180/pi())*60*1.1515) as distance,subscription_types.location_limit as location_limit,users_data.user_id,users_data.last_name,users_data.filename,users_data.user_id,users_data.phone_number,users_data.city,users_data.state_code,users_data.zip_code,users_data.country_code,users_data.quote,users_data.subscription_id,users_data.company,users_data.position,users_data.profession_id,users_data.experience,users_data.account_type,users_data.verified,users_data.nationwide,IF(listing_type = 'Company', company, last_name) as name
FROM `users_data`
LEFT JOIN `users_reviews` ON users_data.user_id=users_reviews.user_id AND users_reviews.review_status='2'
LEFT JOIN users_locations ON users_locations.user_id=users_data.user_id
LEFT JOIN subscription_types ON  users_data.subscription_id=subscription_types.subscription_id
WHERE users_data.active='2'
AND subscription_types.searchable='1'
AND users_data.state_code='CA'
AND users_data.country_code='US'
GROUP BY users_data.user_id
HAVING distance <= '50'
OR location_limit='all'
OR users_data.nationwide='1'
ORDER BY subscription_types.search_priority ASC, distance ASC
LIMIT 0,10

EXPLAIN

  

id select_type表类型possible_keys键key_len ref行额外
  1 SIMPLE users_reviews system user_id,review_status NULL NULL NULL 0 const row not found   1 SIMPLE users_locations系统user_id NULL NULL NULL 0未找到const行   1 SIMPLE users_data ref subscription_id,active,state_code,country_code state_code 47 const 88241使用where;使用临时;使用filesort   1 SIMPLE subscription_types ALL PRIMARY,searchable NULL NULL NULL 4使用where;使用连接缓冲区

1 个答案:

答案 0 :(得分:2)

您的查询并不复杂。在subscription_types表上只有一个连接,这肯定是一个不超过几百行的小表。

  • 你的索引在哪里?改进查询的最佳方法是在您要过滤的字段上创建索引,例如activecountry_codestate_codesearchable
  • 您是否在users_data.subscription_id上创建了外键?你也需要一个索引。
  • ForceIndex没用,让RDBMS确定要选择的最佳索引。
  • 左连接也没用,因为行subscription_types.searchable='1'将删除不匹配的对应
  • search_priority上的顺序意味着您还需要此列上的索引
  • HAVING中的过滤可以使索引不被使用。您无需将这些过滤器放在HAVING中。如果我理解了您的表模式,那么这实际上不是过滤的聚合。

您的表包含100万行,但是返回了多少行,没有限制?使用正确的索引,查询应该在一秒钟内执行。

SELECT ...
FROM `users_data`
    INNER JOIN subscription_types 
        ON users_data.subscription_id = subscription_types.subscription_id 
WHERE users_data.active='2' 
  AND users_data.country_code='US' 
  AND users_data.state_code='NY'
  AND subscription_types.searchable='1'
  AND (distance <= '50' OR location_limit='all' OR users_data.nationwide='1')
GROUP BY users_data.user_id 
ORDER BY subscription_types.search_priority ASC, distance ASC 
LIMIT 0,10