Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >MySQL GeoLocation查询-全表扫描

MySQL GeoLocation查询-全表扫描
EN

Stack Overflow用户
提问于 2016-09-09 14:50:57
回答 1查看 258关注 0票数 0

问题:查找给定经度/纬度的办公室列表

MySQL版本:我们目前使用的是5.5.1

表模式:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
     mysql> describe delivery_office;
     +-------------------------------+--------------+------+-----+---------+-------+
     | Field                         | Type         | Null | Key | Default | Extra |
     +-------------------------------+--------------+------+-----+---------+-------+
     | id                         | bigint(20)   | NO   | PRI | NULL    |       |
     | address_1                  | varchar(255) | YES  |     | NULL    |       |
     | address_2                  | varchar(255) | YES  |     | NULL    |       |
     | address_3                  | varchar(255) | YES  |     | NULL    |       |
     | address_4                  | varchar(255) | YES  |     | NULL    |       |
     | latitude                   | double       | YES  | MUL | NULL    |       |
     | longitude                  | double       | YES  |     | NULL    |       |
     | name                       | varchar(255) | YES  |     | NULL    |       |
     | postcode                   | varchar(255) | YES  |     | NULL    |       |
     | pt_loca                    | point        | NO   | MUL | NULL    |       |
     +-------------------------------+--------------+------+-----+---------+-------+

表索引:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
     mysql> show index from delivery_office;
     +---------------------+------------+--------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+-        --------------+
     | Table               | Non_unique | Key_name     | Seq_in_index | Column_name                | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |         Index_comment |
     +---------------------+------------+--------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+-        --------------+
     | delivery_office |          0 | PRIMARY      |            1 |  id                      | A         |        2156 |     NULL | NULL   |      | BTREE      |                 |               |
     | delivery_office |          1 | geo_index    |            1 | latitude                | A         |        1896 |     NULL | NULL   | YES  | BTREE      |                  |               |
     | delivery_office |          1 | geo_index    |            2 | longitude               | A         |        1939 |     NULL | NULL   | YES  | BTREE      |                  |               | |                 |               |
     | delivery_office |          1 | pt_loca2     |            1 | pt_loca                    | A         |        2156 |       32 | NULL   |      | SPATIAL    |               |               |
     +---------------------+------------+--------------+--------------+----------------------------+-----------+-------------+----------+--------+------+------------+---------+-        --------------+

解决方案:使用地理位置查询来查找它。

我使用了以下解决方案,但这两种解决方案都会导致全表扫描。

我的表只有2168条记录。

Fastest Way to Find Distance Between Two Lat/Long Points

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    mysql> explain SELECT  *
    ->     FROM   delivery_office
    ->     WHERE   MBRContains
    ->                     (
    ->                     LineString
    ->                             (
    ->                             Point (
    ->                             51.5177 + 1 / 111.1,
    ->        -0.0968 + 1 / ( 111.1 /COS(RADIANS(51.5177)))
    ->
    ->                                   ),
    ->                             Point (
    ->                              51.5177 - 1 / 111.1,
    ->               -0.0968 - 1 / ( 111.1 / COS(RADIANS(51.5177)))
    ->
    ->                                   )
    ->                             ),
    ->                     GeomFromText('POINT(51.5177 -0.0968)')
    ->                     );
    +----+-------------+---------------------+------------+------+-----   ----------+------+---------+------+------+----------+-------+
    | id | select_type | table               | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
    +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-------+
    |  1 | SIMPLE      | delivery_office | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 2156 |   100.00 | NULL  |
   +----+-------------+---------------------+------------+------+------     ---------+------+---------+------+------+----------+-------+
    1 row in set, 2 warnings (0.00 sec)

https://gis.stackexchange.com/questions/31628/find-points-within-a-distance-using-mysql

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    mysql> explain EXTENDED SELECT (
    ->      3959 * acos (
    ->        cos ( radians(51.3191750) )
    ->        * cos( radians( latitude ) )
    ->        * cos( radians( longitude ) - radians(-0.5632660) )
    ->        + sin ( radians(51.3191750) )
    ->        * sin( radians( latitude ) )
    ->      )
    ->    ) AS distance_in_miles, delivery_office.*
    ->  FROM delivery_office
    ->  HAVING distance_in_miles < 10
    ->  ORDER BY distance_in_miles
    ->  LIMIT 0 , 30;
    +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+
    | id | select_type | table               | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                       |
    +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+
    |  1 | SIMPLE      | delivery_office | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 2156 |   100.00 | Using where; Using filesort |
    +----+-------------+---------------------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+
    1 row in set, 2 warnings (0.00 sec)

有没有一种方法可以触发查询,而不会导致全表扫描。

EN

回答 1

Stack Overflow用户

发布于 2016-09-12 11:20:27

根据@RickJames的建议,我可以使用这里提供的解决方案来优化查询:

https://www.scribd.com/presentation/2569355/Geo-Distance-Search-with-MySQL https://blog.fedecarg.com/2009/02/08/geo-proximity-search-the-haversine-equation/

以下是使用此优化的结果,行扫描从全表扫描减少到181条记录:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
     mysql> SELECT (
         ->      3959 * acos (
         ->        cos ( radians(51.3191750) )
         ->        * cos( radians( latitude ) )
         ->        * cos( radians( longitude ) - radians(-0.5632660) )
         ->        + sin ( radians(51.3191750) )
         ->        * sin( radians( latitude ) )
         ->      )
         ->    ) AS distance_in_miles
         ->  FROM delivery_office
         ->  where longitude between (-0.5632660 - 10/abs(cos(radians(51.3191750))*69)) and (-0.5632660 + 10/abs(cos(radians(51.3191750))*69)) and latitude between (51.3191750          - (10/69)) and (51.3191750 + (10/69))
         ->  HAVING distance_in_miles < 10
         ->  ORDER BY distance_in_miles
         ->  LIMIT 0 , 10;
     +--------------------+
     | distance_in_miles  |
     +--------------------+
     | 0.3381472408327969 |
     | 1.9060143092544148 |
     |  2.840055550183541 |
     | 3.2969844240913697 |
     |  3.356363831356166 |
     |  4.815726191392366 |
     |  5.134370232935941 |
     |  5.177268204112493 |
     |  5.528244889409913 |
     |  5.702281140258665 |
     +--------------------+
     10 rows in set (0.00 sec)

     mysql> explain EXTENDED SELECT (                                                                                                                                                                                        ->      3959 * acos (
         ->        cos ( radians(51.3191750) )
         ->        * cos( radians( latitude ) )
         ->        * cos( radians( longitude ) - radians(-0.5632660) )
         ->        + sin ( radians(51.3191750) )
         ->        * sin( radians( latitude ) )
         ->      )
         ->    ) AS distance_in_miles
         ->  FROM delivery_office
         ->  where longitude between (-0.5632660 - 10/abs(cos(radians(51.3191750))*69)) and (-0.5632660 + 10/abs(cos(radians(51.3191750))*69)) and latitude between (51.3191750          - (10/69)) and (51.3191750 + (10/69))
         ->  HAVING distance_in_miles < 10
         ->  ORDER BY distance_in_miles
         ->  LIMIT 0 , 10;
     +----+-------------+---------------------+------------+-------+---------------+-----------+---------+------+------+----------+------------------------------------------+
     | id | select_type | table               | partitions | type  | possible_keys | key       | key_len | ref  | rows | filtered | Extra                                    |
     +----+-------------+---------------------+------------+-------+---------------+-----------+---------+------+------+----------+------------------------------------------+
     |  1 | SIMPLE      | delivery_office | NULL       | range | geo_index     | geo_index | 18      | NULL |  181 |    11.11 | Using where; Using index; Using filesort |
     +----+-------------+---------------------+------------+-------+---------------+-----------+---------+------+------+----------+------------------------------------------+
     1 row in set, 2 warnings (0.00 sec)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39414357

复制
相关文章
malloc 背后的虚拟内存 和 malloc实现原理
首先需要知道的是程序运行起来的话需要被加载的物理内存中,具体到计算机硬件就是内存条。操作系统启动的时候先把自己加载到物理内存的固定位置(一般为底部),物理内存的其他位置就用来运行用户程序。程序就是一堆指令,程序运行可以简单抽象为把指令加载到内存中,然后 CPU 将指令从内存载入执行。
C语言与CPP编程
2023/09/06
4840
malloc 背后的虚拟内存 和 malloc实现原理
当我们在谈论内存时,我们在谈论什么
内存,是程序员绕不过的一道坎。写过 C 和 C++ 的人想必都会对内存的手动分配和释放难以忘怀,在 Java 中,得益于 JVM 的自动垃圾回收( GC )机制,大部分情况下编程并不需要关心内存的分配与回收。当然,有了 GC 并不意味着就完事大吉了,如果不了解其中的原理,以错误的姿势滥用 GC ,很有可能翻车酿成不可估量的损失。
用户5397975
2020/02/25
5410
当我们在谈论内存时,我们在谈论什么
探秘malloc是如何申请内存的
我们都清楚malloc申请的内存不是立刻就建立虚拟地址和物理地址的映射的,当int *p = malloc(100*1024)执行这条指令之后,只是在用户空间给程序开辟一段100K左右的大小,然后就返回这段空间的首地址给程序员。
DragonKingZhu
2021/12/07
2.4K1
探秘malloc是如何申请内存的
DPDK 内存管理---malloc_heap和malloc_elem
博文是基于dpdk20.5代码阅读所写,如理解有错误或不当之处,烦请指正,不甚感激。也可以私信我一起探讨。
dpdk-vpp源码解读
2023/01/04
1.4K0
DPDK 内存管理---malloc_heap和malloc_elem
应该对 malloc 返回的值进行转换么
在这个 问题 里,有人在 评论 里建议不要对malloc返回的值进行转换。举个例子,
ClearSeve
2022/02/10
6830
从损坏的手机中获取数据
有时候,犯罪分子会故意损坏手机来破坏数据。比如粉碎、射击手机或是直接扔进水里,但取证专家仍然可以找到手机里的证据。
FB客服
2020/02/23
10.2K0
malloc函数分配内存失败的常见原因
malloc()函数分配内存失败的常见原因: 1. 内存不足。 2. 在前面的程序中出现了内存的越界访问,导致malloc()分配函数所涉及的一些信息被破坏。下次再使用malloc()函数申请内存就会失败,返回空指针NULL(0)。
用户1215536
2019/07/16
5.4K0
【C语言】动态内存开辟的使用『malloc』
​ 所谓动态内存分配(Dynamic Memory Allocation)就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。
謓泽
2022/12/12
8280
【C语言】动态内存开辟的使用『malloc』
Linux进程的内存管理之malloc和mmap
通过《Linxu进程的内存管理》,我们知道了进程内存的最小单位是vma,根据不同的用处又划分了不同类型的vma,比如
刘盼
2021/03/23
5.2K0
十问 Linux 虚拟内存管理 ( 二 )
本文介绍了Linux环境下内存管理的一些基本概念和实现细节,包括分段、分页、虚拟内存、物理内存、缺页异常、页面置换算法、内存池、内存回收和压缩等方面的内容。
陈福荣
2016/11/02
8.7K0
十问 Linux 虚拟内存管理 ( 二 )
c语言中malloc的作用,malloc函数-malloc函数,详解
说明:malloc 向系统申请分配指定size个字节的内存空间。返回类型是 void* 类型。void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。
全栈程序员站长
2022/09/02
2.3K0
【旧文重发 | 07】IC基础知识
[121] 编写UNIX/Linux命令以列出目录中所有文件的名称(例如/usr/bin/dir/)(及其子目录),文件应该包含不区分大小写的“I am preparing for Interview”。
空白的贝塔
2022/05/24
7650
malloc()动态分配内存概述
  2.malloc函数的功能是请求系统分配len个字节的内存空间,如果请求成功,则返回第一个字节的地址,如果请求失败,则返回NULL。
孙晨c
2019/09/10
8740
C++编程常用头文件及其包含函数汇总
【转自】http://blog.csdn.net/linhaiyun_ytdx/article/details/48064065
用户7886150
2021/02/15
1.7K0
使用 Python 删除大于特定值的列表元素
Lambda 函数,通常称为“匿名函数”,与普通的 Python 函数相同,只是它可以在没有名称的情况下定义。def 关键字用于定义普通函数,而 lambda 关键字用于定义匿名函数。但是,它们仅限于单一的表达方式。与常规函数一样,它们可以接受多个参数。
很酷的站长
2023/02/23
10.7K0
使用 Python 删除大于特定值的列表元素
当我们在谈免费游戏时
技术改变思想 本来不想用“当我们在谈XXX的时候,我们在谈什么”这种俗气的标题,但这个文章的内容,确实在一些人的想法里,还是有那么一点俗气的。所以用这个标题,也算文题对应吧。免费游戏,道具收费(Free To Play)作为一种游戏类型的存在,似乎是一个最近10年才开始的事情,但在中国,这种类型几乎成为了唯一的游戏类型。一切产品,都是因为有用户的市场需求才会存在,但是免费游戏这个市场,又是如何被挖掘出来的呢?——这对于看清楚免费游戏背后的用户需求,应该是有很多好处的。 2006年的某天,我的老板给我打了个
韩伟
2018/03/05
2.3K1
当我们在谈免费游戏时
用C来实现内存池
介绍:        设计内存池的目标是为了保证服务器长时间高效的运行,通过对申请空间小而申请频繁的对象进行有效管理,减少内存碎片的产生,合理分配管理用户内存,从而减少系统中出现有效空间足够,而无法分配大块连续内存的情况。 目标:     此次设计内存池的基本目标,需要满足线程安全性(多线程),适量的内存泄露越界检查,运行效率不太低于malloc/free方式,实现对4-128字节范围内的内存空间申请的内存池管理(非单一固定大小对象管理的内存池)。 内存池技术设计与实现     本内存池的设计方法主要参考S
猿人谷
2018/01/17
3.1K1
用C来实现内存池
MYSQL用法(十) 将某字段的值全部+5
一 运用场景:  -- columnName 这里指你的某字段,tablename 这里指你的表名 
Java架构师必看
2021/05/27
1.7K0
面试官不讲武德,居然让我讲讲蠕虫和金丝雀!
  蠕虫是一种可以自我复制的代码,并且通过网络传播,通常无需人为干预就能传播。蠕虫病毒入侵并完全控制一台计算机之后,就会把这台机器作为宿主,进而扫描并感染其他计算机。当这些新的被蠕虫入侵的计算机被控制之后,蠕虫会以这些计算机为宿主继续扫描并感染其他计算机,这种行为会一直延续下去。蠕虫使用这种递归的方法进行传播,按照指数增长的规律分布自己,进而及时控制越来越多的计算机。
嵌入式与Linux那些事
2021/04/20
1.2K0
点击加载更多

相似问题

"malloc():内存损坏“

35

malloc():内存损坏

43

malloc()内存损坏

11

malloc中的内存损坏

10

malloc内存损坏,fopen

31
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文