>  기사  >  백엔드 개발  >  지리적 위치 지리 처리를 위한 mysql 기능의 상세 소개(코드 포함)

지리적 위치 지리 처리를 위한 mysql 기능의 상세 소개(코드 포함)

不言
不言앞으로
2019-03-14 11:20:133060검색

이 기사는 지리적 위치 처리를 위한 mysql 기능(코드 포함)에 대해 자세히 소개합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

현재 LBS, 인근 사람, 테이크아웃 장소, 주변 업체 등을 기반으로 하는 비즈니스가 점점 늘어나고 있습니다. 이제 나에게 가장 가까운 비즈니스 시나리오에 대한 솔루션을 논의하겠습니다.

현재 알려진 솔루션은 다음과 같습니다.

mysql 사용자 정의 함수 계산 mysql geo index mongodb geo index postgresql PostGis index redis geoElasticSearch

이 문서에서는 mysql 함수 작업의 성능을 테스트합니다#🎜🎜 ## 🎜🎜#준비

데이터 테이블 생성

CREATE TABLE `driver` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `lng` float DEFAULT NULL,
  `lat` float DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

테스트 데이터 생성

데이터 생성 전 기본 지리 지식 이해하기:

#🎜🎜 #

글로벌 경도 및 위도 값 범위는 다음과 같습니다.
    위도-90~90, 경도-180~180
  • #🎜🎜 #중국의 위도 및 경도 범위는 대략: 위도 3.86~53.55, 경도 73.66~135.05
  • 베이징 행정 중심지의 위도는 39.92, 경도는 116.46베트남이 클수록 더 큽니다. 현지 위도 값은 동쪽에 있는 곳의 경도 값이 커집니다
  • 도 및 분 변환: 도 및 분 단위 데이터를 도 단위 데이터로 변환, 공식: 도 = 도 + 분 /60#🎜 🎜#
  • 분 및 초 변환: 도, 분, 초 단위 데이터를 도 단위 데이터로 변환합니다. 공식: 도 = 도 + 분 / 60 + 초 / 60 / 60
  • #🎜🎜 #
  • at 위도가 같을 때:
  • 경도는 0.00001도마다, 거리는 약 1미터 정도 다릅니다
#🎜🎜 #경도가 같은 경우: #🎜 🎜#

위도는 0.00001도마다, 거리는 약 1.1미터 정도 차이가 납니다
  • mysql 함수 계산# 🎜🎜#
DELIMITER //
CREATE DEFINER=`root`@`localhost` FUNCTION `getDistance`(
    `lng1` float(10,7) 
    ,
    `lat1` float(10,7)
    ,
    `lng2` float(10,7) 
    ,
    `lat2` float(10,7)

) RETURNS double
    COMMENT '计算2坐标点距离'
BEGIN
    declare d double;
    declare radius int;
    set radius = 6371000; #假设地球为正球形,直径为6371000米
    set d = (2*ATAN2(SQRT(SIN((lat1-lat2)*PI()/180/2)   
        *SIN((lat1-lat2)*PI()/180/2)+   
        COS(lat2*PI()/180)*COS(lat1*PI()/180)   
        *SIN((lng1-lng2)*PI()/180/2)   
        *SIN((lng1-lng2)*PI()/180/2)),   
        SQRT(1-SIN((lat1-lat2)*PI()/180/2)   
        *SIN((lat1-lat2)*PI()/180/2)   
        +COS(lat2*PI()/180)*COS(lat1*PI()/180)   
        *SIN((lng1-lng2)*PI()/180/2)   
        *SIN((lng1-lng2)*PI()/180/2))))*radius;
    return d;
END//
DELIMITER ;
데이터 Python 스크립트 생성# 🎜🎜#
# coding=utf-8
from orator import DatabaseManager, Model
import logging
import random
import threading

""" 中国的经纬度范围 纬度3.86~53.55,经度73.66~135.05。大概0.00001度差距1米 """

# 创建 日志 对象
logger = logging.getLogger()
handler = logging.StreamHandler()
formatter = logging.Formatter(
    '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

# Connect to the database

config = {
    'mysql': {
        'driver': 'mysql',
        'host': 'localhost',
        'database': 'dbtest',
        'user': 'root',
        'password': '',
        'prefix': ''
    }
}

db = DatabaseManager(config)
Model.set_connection_resolver(db)


class Driver(Model):
    __table__ = 'driver'
    __timestamps__ = False
    pass


def ins_driver(thread_name,nums):
    logger.info('开启线程%s' % thread_name)
    for _ in range(nums):
        lng = '%.5f' % random.uniform(73.66, 135.05)
        lat = '%.5f' % random.uniform(3.86, 53.55)

        driver = Driver()
        driver.lng = lng
        driver.lat = lat
        driver.save()

thread_nums = 10
for i in range(thread_nums):
    t = threading.Thread(target=ins_driver, args=(i, 400000))
    t.start()

  • 위 스크립트는 10개의 스레드를 생성하고, 10개의 스레드가 40,000개의 데이터를 삽입합니다. 실행하는데 150.18초가 걸렸고, 총 400,000개의 데이터가 삽입되었습니다. os
Memory: 16G

cpu: intel core i5

#🎜🎜 #하드 드라이브: 500g 솔리드 스테이트 드라이브

테스트 검색 거리(134.38753,18.56734) 이 좌표 지점에 가장 가까운 드라이버 10명지리적 위치 지리 처리를 위한 mysql 기능의 상세 소개(코드 포함)

select *,`getDistance`(134.38753,18.56734,`lng`,`lat`) as dis from driver ORDER BY dis limit 10

소요 시간: 18.0초

explain: 전체 테이블 스캔

#🎜 🎜#
    10,000에서 100,000으로 10,000 간격으로, 100,000에서 900,000으로 100,000 간격으로 결과 변경을 테스트했습니다# 🎜🎜## 🎜🎜#
  • # 🎜🎜#결론

이 솔루션은 데이터 볼륨이 30,000에 도달할 때 쿼리하는 데 1초 이상 걸립니다.

# 🎜🎜#약 10,000마다 추가로 0.4초씩 증가합니다

위 내용은 지리적 위치 지리 처리를 위한 mysql 기능의 상세 소개(코드 포함)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제