优化位置搜索mysql脚本

Posted

技术标签:

【中文标题】优化位置搜索mysql脚本【英文标题】:Optimise location search mysql script 【发布时间】:2015-07-15 15:44:49 【问题描述】:

我正在尝试使用 mysql 从给定的纬度和经度实现“查找最近的位置”。我的 wordpress 网站中存储了 8000 个位置。

我设法写了这个:

SELECT 
   b.ID, 
   SQRT( POW(69.1 * (b.latitude - 51.5073509), 2) + POW(69.1 * (-0.1277583 - b.longitude) * COS(b.latitude / 57.3), 2)) AS distance 
FROM 
   wp_posts a 
LEFT JOIN 
( 
   SELECT 
      post_id AS ID, 
      MAX(CASE WHEN meta_key = 'theme_directory_map_latitude' THEN meta_value ELSE NULL END) AS latitude, 
      MAX(CASE WHEN meta_key = 'theme_directory_map_longitude' THEN meta_value ELSE NULL END) AS longitude 
   FROM 
      wp_postmeta 
   WHERE 
      meta_key = 'theme_directory_map_latitude' OR meta_key = 'theme_directory_map_longitude' 
   GROUP BY 
      post_id 
) b ON a.ID = b.ID 
WHERE 
   a.post_type = 'directory' 
HAVING 
   distance < 30 
ORDER BY 
   distance

上面的脚本可以满足我的需要,但是在我的 weordpress 网站上处理它需要很长时间,有时我什至会出现超时错误。

有没有什么地方可以优化上面的代码,让它运行得更快?

【问题讨论】:

索引,反向查询,不使用wordpress?这更适合codereview.stackexchange.com 这个问题可能适合Code Review,只要 (a) 您的代码按预期工作,(b) 您的代码是真实代码,而不是示例代码,并且 (c) 您的代码包含在问题的正文中。如果您希望通过同行评审来改进代码的各个方面,请将其发布在 Code Review 上。 【参考方案1】:

如果您将group by 替换为显式joins,这可能会更快。这假设每个帖子最多有一个纬度和经度:

SELECT b.ID, 
        SQRT( POW(69.1 * (lat.meta_value - 51.5073509), 2) + POW(69.1 * (-0.1277583 - lng.meta_value) * COS(lat.meta_value / 57.3), 2)) AS distance 
FROM wp_posts p JOIN 
     wp_postmeta lat
     on lat.post_id = p.id and lat.meta_key = 'theme_directory_map_latitude'          
     wp_postmeta lng
     on lng.post_id = p.id and lng.meta_key = 'theme_directory_map_longitude'
WHERE p.post_type = 'directory' 
HAVING distance < 30 
ORDER BY distance;

wp_posts(post_type, id) 上的索引也会有所帮助。 wp_postmeta(post_id, meta_key, meta_value) 上的索引也是如此。

【讨论】:

【参考方案2】:

我通过创建一个新表解决了我的问题,该表包含我试图从连接解决方​​案中提取的字段。

SELECT
               post_id AS ID,
               featured,
               IF(latitude <> '', SQRT( POW(69.1 * (latitude - ".$lat."), 2) + POW(69.1 * (".$lng." - longitude) * COS(latitude / 57.3), 2)), '') AS distance
            FROM
               wp_cbk_location
            HAVING
               (distance < ".$radius." AND distance <> '') OR featured = 1
            ORDER BY
               distance

这个解决方案将我 70 年代的查询变成了 0.13 秒,所以我对这个解决方案很满意。

然后我添加了一个 post_save 操作挂钩,以在我每次保存帖子时更新 wp_cbk_location,以便我创建的新表保持最新。

我还有一个问题,我将提交一个新问题。我可以在 post__in 中拥有的数组中的 id 数量是否有限制?

【讨论】:

以上是关于优化位置搜索mysql脚本的主要内容,如果未能解决你的问题,请参考以下文章

运行Sqoop任务的通用脚本Python2实现(待优化)

运行Sqoop任务的通用模板:Python2脚本实现(待优化)

navicat for MySQL怎么导出SQL脚本

如何执行一个mysql的sql脚本文件

navicat for MySQL怎么导出SQL脚本

如何编写一个mysql数据库脚本