sql >> Database >  >> RDS >> Mysql

Zoeken naar de 5 dichtstbijzijnde locaties bij een postcode - welke kant moet ik op?

Eerst enkele opmerkingen...

Ik heb hier en op andere forums tientallen (niet miljoenen) implementaties gezien; die van jou is beter dan de meeste.

Volgens één gegevensbron (die ik toevallig heb gedownload) zijn er ongeveer 3,2 miljoen steden in de wereld.

Voor prestaties moet u voorkomen dat u alle rijen van 3M controleert. Je hebt een goed begin gemaakt met de groeiende begrenzingsdoos. Merk op dat je moet hebben

INDEX(lat, lon),
INDEX(lon, lat)

De Optimizer kiest tussen deze en de eerste zoekopdracht (met de COUNT(*) ) zal dat als 'bedekkend' zien. Het wordt een streep rond de wereldbol of een wig; een duidelijke verbetering ten opzichte van 3M rijen. De slechtste breedtegraad (+34 graden) heeft 96K steden. (1 graad =69 mijl / 111 km.) Voor een tiende van een graad is 34,4 het ergst, met 10.000 steden.

(Ja, ik geniet van dit soort gegevenspuzzels.)

En ik zie dat je de datumlijn en palen afhandelt. Ik denk niet dat je ze als een speciaal geval kunt verbeteren.

(Ik heb alleen naar de formules en constanten gekeken.)

Geohash en Z-order indexering hulp. Maar ze hebben het probleem dat je tot 4 gebieden rond het doel moet controleren -- het is alsof je je niet realiseert dat de gehele getallen 199999 en 200000 heel dicht bij elkaar liggen, ondanks dat het eerste cijfer van elk verschillend is.

"Gebruiker geeft postcode of plaatsnaam in" - dat is een puntzoekopdracht in een van de twee eenvoudige tabellen. (Behalve dat er dups kunnen zijn -- meer dan 320 elk van "san jose" en "san antonio". Vrij ver onderaan de lijst staat de eerste niet-Spaanse naam:"victoria", met slechts 144 steden.)

Ten tweede, mijn implementatie... (Het heeft enkele overeenkomsten met de jouwe.)

http://mysql.rjweb.org/doc.php/latlng

Dit verbetert de prestaties door gebruik te maken van PARTITIONing om het selectiekader tot ongeveer een vierkant te houden, in plaats van een streep of wig. Als je op zoek bent naar de 5 dichtstbijzijnde, zal mijn algoritme zelden meer dan enkele tientallen rijen raken, en die rijen zullen worden 'geclusterd' in een klein aantal blokken, waardoor het aantal schijfhits erg laag blijft.

Een cruciaal punt in mijn ontwerp is om alle benodigde kolommen in één tabel te hebben. Zodra je de dichtstbijzijnde 5 hebt gevonden, kun je naar andere tafels gaan om aanvullende dingen te krijgen (telefoonnummer, enz.).

Wat betreft postcodes, verander ze in lat/lon voordat u begint met zoeken naar de 5 dichtstbijzijnde.

Een join binnen het algoritme zal zeer waarschijnlijk de prestatie vernietigen.



  1. set-namen vs mysqli_set_charset - zijn ze, behalve dat ze van invloed zijn op mysqli_escape_string, identiek?

  2. Codeigniter toont lege pagina zonder fout

  3. Hoe verkeerd gecodeerde gegevens naar UTF-8 te converteren?

  4. Toon willekeurig mysql-resultaat