IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

[MySQL-5.7.11] Optimisation de requête geonames


Sujet :

Requêtes MySQL

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Chômeur
    Inscrit en
    Août 2016
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Chômeur

    Informations forums :
    Inscription : Août 2016
    Messages : 18
    Points : 9
    Points
    9
    Par défaut [MySQL-5.7.11] Optimisation de requête geonames
    Bonjour à tous,

    je travail actuellement sur un projet qui utilise la géolocalisation.
    Et notamment la fameuse BDD Geonames.
    J'ai réussi à intégré toute les données dans mon MySQL (je vous dis pas combien de temps ça m'a pris ).
    Merci à ce site : http://codigofuerte.github.io/GeoNam...QL-DataImport/
    Pour optimiser les tables pour certaine requêtes j'ai suivi ce site : http://www.developpeur-php-independa...geonames-suite
    Cependant j'ai eu un problème pour créer l'index
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE `geoname` ADD INDEX `alternatenames` USING BTREE(`alternatenames`);
    Car mysql me répond que la clef est supérieur à la taille maximum qui est de 3072, c'est un varchar(4000), ça passe pas...

    Je souhaite récupérer les villes autour d'une localisation avec un périmètre.
    Bon ça fonctionne, cependant mon exécution si je cible sur la France dure entre 4-5s.
    Pour le monde complet je suis à 60-61s.
    Ces temps de traitement ne me vont pas et j'essaye de trouver des idées pour arriver à un temps correct.

    Ma requête actuelle FR (PHP) :
    4-5s
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    $formule = "(6366*acos(cos(radians($latitude))*cos(radians(g2.latitude))*cos(radians(g2.longitude)-radians($longitude))+sin(radians($latitude))*sin(radians(g2.latitude))))";
    $sql = "
        SELECT DISTINCT
            g1.geonameid,
            g1.name,
            g1.fclass
        FROM geoname g1
        LEFT JOIN geoname g2 ON g1.geonameid = g2.geonameid
        WHERE $formule <= '$perimetre'
        AND g1.fcode LIKE 'PPL%'
        AND g1.country = 'FR'
    ";
    EXPLAIN :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    array (size=2)
      0 => 
        array (size=9)
          'select_type' => string 'SIMPLE' (length=6)
          'table' => string 'g1' (length=2)
          'type' => string 'ref' (length=3)
          'possible_keys' => string 'PRIMARY,fcode,country,fcode_2' (length=29)
          'key' => string 'country' (length=7)
          'key_len' => string '9' (length=1)
          'ref' => string 'const' (length=5)
          'rows' => string '282632' (length=6)
          'Extra' => string 'Using where; Using temporary' (length=28)
      1 => 
        array (size=9)
          'select_type' => string 'SIMPLE' (length=6)
          'table' => string 'g2' (length=2)
          'type' => string 'eq_ref' (length=6)
          'possible_keys' => string 'PRIMARY' (length=7)
          'key' => string 'PRIMARY' (length=7)
          'key_len' => string '4' (length=1)
          'ref' => string 'geoname.g1.geonameid' (length=20)
          'rows' => string '1' (length=1)
          'Extra' => string 'Using where; Distinct' (length=21)
    La version monde :
    60-61s
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    $formule = "(6366*acos(cos(radians($latitude))*cos(radians(g2.latitude))*cos(radians(g2.longitude)-radians($longitude))+sin(radians($latitude))*sin(radians(g2.latitude))))";
    $sql = "
        SELECT DISTINCT
            g1.geonameid,
            g1.name,
            g1.fclass
        FROM geoname g1
        LEFT JOIN geoname g2 ON g1.geonameid = g2.geonameid
        WHERE $formule <= '$perimetre'
        AND g1.fcode LIKE 'PPL%'
    ";
    EXPLAIN :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    array (size=2)
      0 => 
        array (size=9)
          'select_type' => string 'SIMPLE' (length=6)
          'table' => string 'g1' (length=2)
          'type' => string 'ALL' (length=3)
          'possible_keys' => string 'PRIMARY,fcode,fcode_2' (length=21)
          'key' => null
          'key_len' => null
          'ref' => null
          'rows' => string '10584103' (length=8)
          'Extra' => string 'Using where; Using temporary' (length=28)
      1 => 
        array (size=9)
          'select_type' => string 'SIMPLE' (length=6)
          'table' => string 'g2' (length=2)
          'type' => string 'eq_ref' (length=6)
          'possible_keys' => string 'PRIMARY' (length=7)
          'key' => string 'PRIMARY' (length=7)
          'key_len' => string '4' (length=1)
          'ref' => string 'geoname.g1.geonameid' (length=20)
          'rows' => string '1' (length=1)
          'Extra' => string 'Using where; Distinct' (length=21)
    Si quelqu'un connais bien l'optimisation de requête et à des idées pour arrivé à une exécution requête monde de moins d'une seconde je suis preneur !!

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 760
    Points : 52 541
    Points
    52 541
    Billets dans le blog
    5
    Par défaut
    MySQL étant l'un des plus mauvais SGDBR en terme de performance et de plus fortement bugué dans sa partie spatiale, je ne saurait trop vous conseiller d'aller sur un autre SGBDR comme PostGreSQL ou SQL Server qui optimisent ce genre de chose sans aucun problème....

    À lire sur MySQmerde.... :
    http://blog.developpez.com/sqlpro/p9...oudre_aux_yeux

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Chômeur
    Inscrit en
    Août 2016
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Chômeur

    Informations forums :
    Inscription : Août 2016
    Messages : 18
    Points : 9
    Points
    9
    Par défaut
    J'ai testé de mettre en local un postgreSQL et effectivement sur la même requête je passe de 60s avec MySQL à 10s avec PostgreSQL.
    Cependant je trouve ça quand même long 10s. Je vais essayer de voir si je peu pas encore améliorer ça.

    Étant hébergé chez OVH pour passer sur du PostgreSQL ça va me couter de l'argent :'( mais bon je crois que je vais pas avoir le choix.

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Chômeur
    Inscrit en
    Août 2016
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Chômeur

    Informations forums :
    Inscription : Août 2016
    Messages : 18
    Points : 9
    Points
    9
    Par défaut
    J'ai oublié de te remercier pour ta réponse SQLPro, donc merci !!

    En passant par la table postalcodes j'en suis à 6708.43 ms :
    Requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT DISTINCT
        pc1.placename
    FROM postalcodes pc1
    LEFT JOIN postalcodes pc2 ON pc1.placename = pc2.placename
    WHERE (6366*acos(cos(radians(48.0012))*cos(radians(pc2.latitude))*cos(radians(pc2.longitude)-radians(2.7536))+sin(radians(48.0012))*sin(radians(pc2.latitude)))) <= '10'
    Schéma :
    Nom : postalcodes_schema.png
Affichages : 179
Taille : 46,5 Ko

    Si quelqu'un à encore une idée pour améliorer le temps d’exécution de ma requête je suis preneur

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 760
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 760
    Points : 52 541
    Points
    52 541
    Billets dans le blog
    5
    Par défaut
    Trois remarques...
    1) Pourquoi fais tu des calculs immondes alors qu'il existe des opérateurs spatiaux ???
    par exemple pour savoir si 2 géométries sont distantes de moins de 10 mètres, il suffit de faire :
    ST_Distance(Geo1, Geo2) < 10
    2) Pourquoi passer un nombre sous forme de chaine de caractères ? Ceci affecte les performances car oblige à un transtypages ! Les BD relationnelles ont des données FORTEMENT typées !!! Donc 10 et non pas '10' !
    3) poser un index spatial permet d'accélérer certaines recherches

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

Discussions similaires

  1. Optimiser ma requête MySQL
    Par lusitain91 dans le forum Requêtes
    Réponses: 2
    Dernier message: 06/01/2015, 22h33
  2. [MySQL] [MySQL] Optimisation de requête
    Par Falistos dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 30/06/2009, 08h51
  3. [MySQL] Optimisation de requêtes MySql
    Par oclone dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 11/07/2008, 11h20
  4. Réponses: 4
    Dernier message: 29/11/2007, 10h56
  5. Optimiser une requête mysql
    Par Raideman dans le forum Requêtes
    Réponses: 2
    Dernier message: 05/09/2007, 21h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo