Heim >Backend-Entwicklung >Python-Tutorial >Detaillierte Einführung der MySQL-Funktion für die Geoverarbeitung von geografischen Standorten (mit Code)

Detaillierte Einführung der MySQL-Funktion für die Geoverarbeitung von geografischen Standorten (mit Code)

不言
不言nach vorne
2019-03-14 11:20:133129Durchsuche

Dieser Artikel bietet Ihnen eine detaillierte Einführung in die MySQL-Funktion zur Geoverarbeitung (mit Code). Ich hoffe, dass er Ihnen als Referenz dienen wird.

Derzeit basieren immer mehr Unternehmen auf LBS, Personen in der Nähe, Take-out-Standorten, Geschäften in der Nähe usw. Jetzt werden wir die Lösung für das Geschäftsszenario besprechen, das mir am nächsten kommt.

Derzeit bekannte Lösungen sind:

Berechnung benutzerdefinierter MySQL-Funktionen, MySQL-Geo-Index, Mongodb-Geo-Index, Postgresql, PostGis-Index, Redis, GeoElasticSearch

Dieser Artikel testet die Leistung der MySQL-Funktionsoperation

Vorbereitungsarbeiten

Datentabelle erstellen

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;

Testdaten erstellen

Verstehen Sie grundlegende geografische Kenntnisse, bevor Sie Daten erstellen:

  • Der Wertebereich des globalen Längengrads und Breitengrad ist: Breitengrad -90~90, Längengrad -180~180
  • Chinas Längen- und Breitengradbereich beträgt ungefähr: Breitengrad 3,86~53,55, Längengrad 73,66~135,05
  • Der Breitengrad des Verwaltungszentrums von Peking beträgt 39,92 und der Längengrad 116,46
  • Je weiter nördlich, desto größer der Breitengradwert, je weiter östlich, desto größer der Längengradwert
  • Grad und Minute Umrechnung: Grad- und Minuteneinheitsdaten in Gradeinheitsdaten umwandeln, Formel: Grad = Grad + Minute/60
  • Minuten- und Sekundenumrechnung: Grad-, Minuten- und Sekundeneinheitsdaten in Gradeinheitsdaten umwandeln, Formel: Grad = Grad + Minute / 60 + Sekunden / 60 / 60

Bei gleichem Breitengrad:

  • Der Längengrad beträgt alle 0,00001 Grad, der Abstand unterscheidet sich um etwa 1 Meter

Wenn die Längengrade gleich sind:

  • Der Breitengrad beträgt alle 0,00001 Grad und der Abstand unterscheidet sich um etwa 1,1 Meter

MySQL-Funktionsberechnung

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 ;

Daten-Python-Skript erstellen

# 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()

Detaillierte Einführung der MySQL-Funktion für die Geoverarbeitung von geografischen Standorten (mit Code)

Das obige Skript erstellt 10 Threads und 10 Threads fügen 40.000 Daten ein. Die Ausführung dauerte 150,18 Sekunden und es wurden insgesamt 400.000 Datenelemente eingefügt

Test

  • Testumgebung

System: Mac OS

Speicher: 16G

CPU: Intel Core i5

Festplatte: 500g Solid State Drive

Finden Sie im Rahmen des Tests die 10 Treiber, die dem Koordinatenpunkt am nächsten liegen (134.38753,18.56734)

select *,`getDistance`(134.38753,18.56734,`lng`,`lat`) as dis from driver ORDER BY dis limit 10
  • Zeitaufwändig: 18,0 Sekunden
  • Erklärung: Vollständiger Tabellenscan

Ich habe das Intervall von 10.000 bis 100.000 mal 10.000 getestet und von 100.000 auf 90 Änderungen der Ergebnisse alle 100.000 Tests

Detaillierte Einführung der MySQL-Funktion für die Geoverarbeitung von geografischen Standorten (mit Code)

Fazit

  • Diese Lösung benötigt mehr als eine Abfrage, wenn das Datenvolumen 30.000 erreicht Sekunden
  • Ungefähr alle 10.000 zusätzlichen Einträge erhöht sich der Zeitverbrauch um 0,4 Sekunden

Das obige ist der detaillierte Inhalt vonDetaillierte Einführung der MySQL-Funktion für die Geoverarbeitung von geografischen Standorten (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen