Dites que je veux trouver les 20 entreprises les plus proches de chez moi.
My table structure is like this:
BusinessID varchar(250) utf8_unicode_ci No None Browse distinct values Change Drop Primary Unique Index Fulltext
Prominent double No None Browse distinct values Change Drop Primary Unique Index Fulltext
LatLong point No None Browse distinct values Change Drop Primary Unique Index Fulltext
FullTextSearch varchar(600) utf8_bin No None Browse distinct values Change Drop Primary Unique Index Fulltext
With selected: Check All / Uncheck All With selected:
Print viewPrint view Propose table structurePropose table structureDocumentation
Add new fieldAdd field(s) At End of Table At Beginning of Table After
Indexes: Documentation
Action Keyname Type Unique Packed Field Cardinality Collation Null Comment
Edit Drop PRIMARY BTREE Yes No BusinessID 1611454 A
Edit Drop Prominent BTREE No No Prominent 0 A
Edit Drop LatLong BTREE No No LatLong (25) 0 A
Edit Drop sx_mytable_coords SPATIAL No No LatLong (32) 0 A
Edit Drop FullTextSearch FULLTEXT No No FullTextSearch 0
Il y a 1,6 million de biz. Bien sûr, il est stupide de calculer la distance pour chacun d'eux, puis de la trier.
C'est là que l'index géospatial entre en jeu, non?
Alors, quel comman SQL je dois lancer?
Remarque:
- J'utilise MySQL MyISAM index spatial. Cependant, je n'ai pas précisé cela auparavant. Je vais donc accepter ceux qui y répondent pour montrer mon appréciation et poser une autre question.
- Je ne veux pas calculer la distance pour toute la table
- Je ne veux calculer la distance pour aucune région encore inefficace
- Je veux calculer la distance pour un nombre raisonnable de points parce que je veux trier les points par distance et pouvoir afficher les points 1-20, 21-40, 41-60, etc.
Réponses:
Les requêtes spatiales sont certainement la chose à utiliser.
Avec PostGIS, j'essaierais d'abord quelque chose de simpliste comme celui-ci et modifierais la plage selon les besoins:
Cela comparerait des points (en fait leurs boîtes englobantes) en utilisant l'index spatial, donc cela devrait être rapide. Une autre approche qui vient à l'esprit est la mise en mémoire tampon de votre emplacement, puis l'intersection de cette mémoire tampon avec les données d'origine, ce qui peut être encore plus efficace.
la source
Si tout ce que vous recherchez sont des recherches de points de proximité (requêtes de voisins les plus proches), vous ne voulez pas utiliser les anciens ST_DWithin ou ST_Distance + ORDER BY pour cela.
Plus maintenant.
Maintenant que PostGIS 2.0 est livré, vous devez utiliser la prise en charge de l'index knngist (une fonctionnalité native de PostgreSQL). Ce sera des ordres de grandeur plus rapidement.
Un extrait de cette entrée de blog qui décrit comment utiliser knn gist sans PostGIS :
Assez intéressant, la traversée d'index renverra les caractéristiques par ordre de proximité, donc pas besoin de faire un tri (c'est-à-dire par ordre) pour les résultats!
Cependant, si vous souhaitez l'utiliser avec PostGIS, c'est désormais très simple. Suivez simplement ces instructions .
La partie pertinente est la suivante:
Mais ne me croyez pas sur parole. Temps vous-même :)
la source
Avec PostGIS 2.0 sur PostgreSQL 9.1, vous pouvez utiliser l'opérateur de voisin le plus proche indexé KNN , par exemple:
Ce qui précède devrait interroger en quelques millisecondes.
Pour les prochains multiples de 20, à modifier
OFFSET 20
,OFFSET 40
etc ...la source
<->
? Merci.<->
est un opérateur qui renvoie la distance 2D.MySQL Spatial
Tout le monde ici vous explique comment le faire avec PostgreSQL en utilisant KNN, sans vous en dire les avantages. En utilisant MySQL, vous ne pouvez pas déterminer le voisin le plus proche sans calculer la distance pour tous les voisins. C'est extrêmement lent. Avec PostgreSQL, cela peut être fait sur un index. Ni MySQL ni MariaDB ne prennent actuellement en charge KNN
la source