3分鐘瞭解Mysql空間搜GeoHash

來源:互聯網
上載者:User

標籤:geohash

簡單介紹:

   Mysql 內建函數方案,適合於已有業務,新增加LBS功能,增加經緯度欄位方可,避免資料移轉,在5.7.5後實現更多功能實現INNODB的空間搜方法,之前版本主要是對MYISAM的支援。

    在此之前,InnoDB將幾何資料存放區為BLOB(二進位大對象)資料,在空間資料上只能建立首碼索引,當涉及空間搜尋時非常低效,尤其是在涉及複雜的幾何資料時。在大多數情況下,獲得結果的唯一方式是掃描表。

    新版本MySQL中,InnoDB支援空間索引,通過R樹來實現,使得空間搜尋變得高效,如使用內建函數(MBRWITHIN MBRCONTAINS)效率非常好。但目前空間索引只支援兩個維度資料。


應用情境介紹:

    公司新業務的需求,希望能夠實現當前位置快速顯示共用資訊資料,針對5.7新特性的支援度調研,利用GeoHash封裝成內建資料庫函數的簡易方案,實現前期的初期業務。

實現過程:

  1、構建表

    CREATE TABLE `tongzhou` (

      `id` INT(11) NOT NULL AUTO_INCREMENT,

      `cname` VARCHAR(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,

      `oint` POINT NOT NULL,

      PRIMARY KEY (`id`),

      SPATIAL KEY `sp_index` (`oint`)

    ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

  2、構造簡單資料

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘景欣園 ‘,‘POINT(39.8885917679 116.6576038966)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘京通羅斯福廣場‘,‘POINT(39.8890214887 116.6473661241)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘中國北京市北京市通州區‘,‘POINT(39.8898670523 116.6566729546)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘中國北京市北京市通州區‘,‘POINT(39.8883852752 116.655728817)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘楊莊路22號院‘,‘POINT(39.8984936518 116.6339063644)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘中國北京市北京市朝陽區 ‘,‘POINT(39.8975388526 116.613779068)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘北京市朝陽區第三醫院 約31米‘,‘POINT(39.8873809413 116.603307724)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘雙橋溫泉北裡小區‘,‘POINT(39.8918427053 116.6076636314)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘京客隆配送中心‘,‘POINT(39.8916616061 116.5908622742)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘世紀賓館‘,‘POINT(39.8918591688 116.6024065018)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘雙橋六號井小區-北區 約48米‘,‘POINT(39.8899164443 116.6050457954)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘翠屏裡小區 約190米‘,‘POINT(39.8883194176 116.6495060921)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘京通羅斯福廣場‘,‘POINT(39.8894719148 116.6584646702)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘life新生活廣場 約87米‘,‘POINT(39.8895542353 116.65579319)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘life新生活廣場 約74米‘,‘POINT(39.8896242077 116.6568982601)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘life新生活廣場‘,‘POINT(39.8901428239 116.6564154625)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘漫春園‘,‘POINT(39.8913364496 116.658115983)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘7天連鎖酒店(北京通州果園環島店) 約58米‘,‘POINT(39.8915998677 116.6560935974)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘北京金松賓館 約77米‘,‘POINT(39.9036172391 116.6577833891)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘新華南路小區-東區 約32米‘,‘POINT(39.9034444015 116.6588240862)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘紅旗小區 約61米‘,‘POINT(39.9046707164 116.6598540545)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘祥雲天地家園 約62米‘,‘POINT(39.9067899674 116.659129858)‘);

    insert into `tongzhou` (`cname`, `ASTEXT(oint)`) values(‘梨園地鐵站 約40米‘,‘POINT(39.8832975966 116.6687965393)‘);


  3、搜尋當前1公裡範圍內的位置資訊

    SET @jl=1;  //多少公裡範圍內的

    SET @jd=118.1964111328;

    SET @wd=39.5591182422;  //當前的位置資訊

    oint是實際已經存在的經緯度資訊

     SELECT *,ASTEXT(oint)FROM  tongzhou WHERE  MBRCONTAINS( LINESTRING(POINT( @wd + @jl / ( 111.12 / COS(RADIANS(@jd))), 

    @jd + @jl / 111.12  ),  

    POINT  ( @wd - @jl / ( 111.12 / COS(RADIANS(@jd))),@jd - @jl / 111.12)  ), oint) 

    ###經緯弧度(1° latitude = 111.12 kilometers)即 10/111.12,表示尋找附近10公裡。

  4、測試

    通過百度地圖擷取一些資料,對

         SET @jd=118.1964111328

         SET @wd=39.5591182422

        值的更新,分析擷取範圍內的景點資訊


  5、問題:

     如果直接在WHERE採用一系列的運算式,這樣會導致無法使用空間索引,:

650) this.width=650;" src="https://s2.51cto.com/oss/201711/11/2fa268136801e296920360f50ace6d02.png-wh_500x0-wm_3-wmp_4-s_2852158178.png" title="a11.png" alt="2fa268136801e296920360f50ace6d02.png-wh_" />

解決辦法:
     1、把WHERE後的運算式處理成一個變數進行引用,然後進行周邊搜    

    SET @aa=(SELECT LINESTRING(POINT( 39.5591182422 + 10/ ( 111.12 / COS(RADIANS(118.1964111328))), 

    118.1964111328 + 10 / 111.12  ),  

    POINT  ( 39.5591182422 - 10 / ( 111.12 / COS(RADIANS(118.1964111328))),118.1964111328 -10 / 111.12)) AS  heji)

     2、執行周邊搜

       SELECT ASTEXT(oint)FROM  tongzhou WHERE  MBRWITHIN(@aa,oint)

   順帶執行計畫效果:

      650) this.width=650;" src="https://s3.51cto.com/oss/201711/11/052ca10b26528e25d9ca6f86d428f596.png-wh_500x0-wm_3-wmp_4-s_39204127.png" title="gtid2.png" alt="052ca10b26528e25d9ca6f86d428f596.png-wh_" />


拍磚了。。。。。。

本文出自 “DBAspace” 部落格,請務必保留此出處http://dbaspace.blog.51cto.com/6873717/1980877

3分鐘瞭解Mysql空間搜GeoHash

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.