2010-07-25 6 views
2

J'ai une table de 320000 lignes qui contient des points de coordonnées lat/lon. Lorsqu'un utilisateur sélectionne un emplacement, mon programme obtient les coordonnées à partir de l'emplacement sélectionné et exécute une requête qui amène tous les points de la table qui sont proches. Ceci est fait en calculant la distance entre le point sélectionné et chaque point de coordonnée de ma rangée de table. Ceci est la requête que j'utilise:Optimisation de la requête Sqlite pour INDEX

select street from locations 
where ( ((lat - (-34.594804)) *(lat - (-34.594804))) + ((lon - (-58.377676))*(lon - (-58.377676))) <= ((0.00124)*(0.00124))) 
group by street; 

Comme vous pouvez le voir la clause WHERE est une formule simple Pythagore pour calculer la distance entre deux points. Maintenant, mon problème est que je ne peux pas obtenir un INDEX pour être utilisable. Je l'ai essayé avec

CREATE INDEX indx ON location(lat,lon) 

aussi avec

CREATE INDEX indx ON location(street,lat,lon) 

sans chance. J'ai remarqué que quand il y a une opération mathématique avec lat ou lon, l'index n'est pas appelé. Est-il possible d'optimiser cette requête pour utiliser un INDEX afin d'obtenir des résultats rapides?

Merci d'avance!

Répondre

0

Vous avez sûrement une clé primaire dans les emplacements? Probablement appelé id? Pourquoi ne pas simplement sélectionner l'ID avec la rue?

select id, street from locations 
where ( ((lat - (-34.594804)) *(lat - (-34.594804))) + ((lon - (-58.377676))*(lon - (-58.377676))) <= ((0.00124)*(0.00124))) 
group by street; 
+0

Salut Zane, pour autant que je lis, un index n'est appelé que s'il y a une clause WHERE qui a des colonnes (dans mon cas lat et lon) qui apparaissent dans l'index. L'ajout de la colonne id à côté de SELECT ne semble pas accélérer les choses. Merci! http://www2.sqlite.org/optoverview.html –

1

Avez-vous essayé d'ajuster le page size? Une table comme celle-ci pourrait gagner à avoir une taille de page différente (c'est-à-dire la plus grande?) Disponible.

PRAGMA page_size = 32768; 

ou toute puissance de 2 entre 512 et 32768. Si vous changez le page_size, n'oubliez pas de vide de la base de données (en supposant que vous utilisez 3.5.8 SQLite. Sinon, vous ne pouvez pas le changer et devra commencer une nouvelle base de données fraîche).

En outre, l'opération en cours d'exécution sur les flotteurs pourrait ne pas être aussi rapide que la course sur des entiers (grand peut-être), de sorte que vous pourriez gagner de la vitesse si vous enregistrez toutes vos coordonnées fois 1 000 000

Enfin, euclydian la distance ne donnera pas des résultats de proximité très précis. Plus vous allez loin de l'équateur, plus le cercle autour de votre point s'aplatira pour ressembler à une ellipse. Il y a des approximations rapides qui ne sont pas un calcul aussi intense qu'un calcul de distance de grand cercle (évitez à tout prix!)

+0

Hey! Merci pour votre réponse !!, j'ai essayé d'utiliser le calcul de distance Great Circle et comme vous l'avez dit, c'est un calcul très intense, savez-vous un moyen plus rapide de calculer les distances de coordonnées? –

+0

Tout dépend de la précision avec laquelle vous voulez calculer. Un calcul convertit les degrés en mètres. Aux latitudes, cela sera toujours constant, mais en longitude qui varie selon votre latitude, donc 1 degré de longitude (Earth_Circumference/360) * cos (latitude). La latitude sera d'environ 40 008 km/360 = 111,133 km pour 1 degré. La longitude sera d'environ 40 075 km/360 = 111,319 km * cos (latitude) pour 1 degré. Voyez comment Pythagore aime celui-ci :) – MPelletier

1

Vous devriez chercher dans un carré au lieu d'un cercle. Ensuite, vous serez en mesure d'optimiser.

2

Le problème est que le moteur sql doit évaluer tous les enregistrements pour effectuer la comparaison (WHERE ..... < = ...) et filtrer les points afin que les index n'accélèrent pas la requête. Une approche pour résoudre le problème consiste à calculer une latitude et une longitude minimales et maximales afin de restreindre le nombre d'enregistrements. Voici un bon lien à suivre: Finding Points Within a Distance of a Latitude/Longitude