2017-05-22 5 views
0

J'ai des données géospatiales, noms avec des coordonnées, dans une table SQLite et créé un arbre pour l'emplacement et un index normal sur la colonne nom.Requête SQLite utilisant rtree et index normal lent

RTree est utilisé selon cette docs: http://www.sqlite.org/rtree.html

Lorsque je fais une recherche des enregistrements dans une zone spécifique, le rtree est utilisé et cela fonctionne rapidement:

SELECT demo_data.* FROM demo_data, demo_index 
WHERE demo_data.id=demo_index.id 
    AND minX>=-81.0 AND maxX<=-79.6 
    AND minY>=35.0 AND maxY>=36.2; 

Quand je QUERY pour les noms, il va aussi vite, parce que le nom-index est utilisé:

SELECT demo_data.* FROM demo_data 
WHERE objname="Test" 

Mais quand je combine les deux, son semble très lent, comme toute la table est analysé:

SELECT demo_data.* FROM demo_data, demo_index 
WHERE demo_data.id=demo_index.id 
    AND objname="Test" 
    AND minX>=-81.0 AND maxX<=-79.6 
    AND minY>=35.0 AND maxY>=36.2; 

Pourquoi cette requête combinée utilisant deux index est-elle si lente?

Mise à jour:

Après une enquête plus approfondie avec EXPLIQUER QUERY PLAN, il est apparu que les index sont effectivement utilisés par chaque condition individuelle. Mais le temps d'exécution de la requête combinée dépend du nombre d'enregistrements dans la première condition. Cette table demo_data a 10mio enregistrements. mais la combinaison n'est lente que si la première condition renvoie beaucoup d'enregistrements. Dans ce cas, il y a environ 1000 enregistrements avec objname = "Test" et la requête combinée prend 4 secondes. Une requête combinée pour objname = "Test12345", qui n'existe qu'une seule fois, est très rapide, seulement 10ms

Répondre

1

Les requêtes impliquant plus d'un index sont difficiles à accélérer et peuvent nécessiter des statistiques, peut-être même à partir de requêtes antérieures.

La base de données pourrait (je ne sais pas ce que SQLite mis en œuvre), par exemple:

  1. sous caution dehors, et toujours faire un balayage lent
  2. Utilisez le premier index uniquement, scanner les lignes correspondantes
  3. Utilisez le second index seulement, analyser les lignes correspondantes
  4. Obtenir ID des deux index, recouper, reconstruire ensuite toutes les lignes

Il » s la tâche de l'optimiseur de requête de choisir la meilleure stratégie. Souvent, 2 ou 3 est le meilleur, si nous pouvons prédire quel indice donne le plus petit résultat. Il nécessite des statistiques obtenues lors de l'appel ANALYZE.

Utilisez EXPLAIN QUERY PLAN SELECT ... pour voir ce que SQLite a décidé de faire: https://sqlite.org/eqp.html

Vous pouvez également essayer les requêtes imbriquées pour pousser l'optimiseur vers le meilleur plan, et vous devriez lire la documentation optimiseur de requête: https://www.sqlite.org/optoverview.html

+0

remerciements pour mentionner EXPLAIN QUERY PLAN. Cela a montré que les index étaient réellement utilisés. La raison de l'exécution lente est la quantité de données. J'ai mis à jour ma question – Tom