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

PHP & Base de données Discussion :

execution table temporaire ? [MySQL]


Sujet :

PHP & Base de données

  1. #1
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut execution table temporaire ?
    Bonjour,

    Voila une question un peu technique, j'ai une requete lourde que j'aimerai simplifier en créant une table temporaire lors de la conexion du user ,
    Cela peut vous paraitre bete , mais comment faire en sorte que la requete pour ma table temp ne soit exécuter qu'un seule fois . Je comptais
    créer ma table temp dés conexion du user en la mettant dans le header par ex.

    Mais.. Comme le header se charge à chaque fois, la table temp est recréer a chaque fois ??

    Désolé si je vous parait stupide , je débute..

    Jess

  2. #2
    Membre expérimenté
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2010
    Messages
    144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Décembre 2010
    Messages : 144
    Par défaut
    Si le but de cette table temporaire est de récupérer des informations sans avoir une requête trop lourde alors il vaut mieux utiliser les vues : http://dev.mysql.com/doc/refman/5.0/fr/views.html

    Une vue se comporte comme une "table virtuelle", son contenu est mis à jour automatiquement lorsque les tables auxquelles elle est rattaché sont modifiées.

  3. #3
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    salut,

    pas dans mysql, c'est une plutôt requête encapsulée, exécutée à chaque appel à la vue...

    dans d'autres sgbd c'est en effet plutôt une table temporaire remise à jour en fonction des dépendances...

    si tu as une page dynamique et que son contenu n'est pas mis en cache oui ça s'exécutera à chaque appel de la page...

    pour les table temporaire je t'ai répondu dans ton autre post dans la section mysql...

  4. #4
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut
    Salut, merci pour les liens,

    jai lu un peu plus sur les vues, et je en pense pas que les utiliser
    puisse me faire gagner en performance car la requete qui construit la vue est apelé a chaque requete sur cette dite vue.
    L'idée n'étant pas de simplifier la requete mais de précalculé des info.

    Pour etre précis je dois calculer des distance avec latitude et longitude,
    mon objectif étant de précalculer a la conexion pour faire un tri sur résultat
    avec between sur la table temporaire crée. Ca vous parait sencé ?
    une ptite confirmation ne serait pas de refus !

  5. #5
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    si tu veux gagner alors fais une procédure stockée

    dedans:
    • tu détermines le carré englobant la zone où tu vas appliquer la formule de distance, ce qui va te délimiter rapidement les données où tu vas appliquer la formule de distance:
      • tu détermines le demi écart horizontal et le demi écart vertical
      • tu les ajoutes et soustrais aux coordonnées de référence pour obtenir les valeurs min et max de longitude et latitude
    • tu construis ensuite une requête interne (allant dans le from d'une autre que j'appellerais externe ici) qui sélectionne les données en appliquant 2 between (1 sur les longitudes, 1 sur les latitudes) avec les valeur min/max précédemment calculées.
    • tu construis alors ta requête externe autour pour appliquer la formule de distance en entourant la requête interne avec des parenthèses et en la renommant avec une lettre par exemple comme une table que tu renommes


    pour rappel 1MN = 1'arc en latitude = 1852m
    soit x la distance en m que tu cherches:
    • en latitude: ecartlat*60*1852=x donc ecartlat=x/111120
    • en longitude: ecartlon*111120*cos(lat)=x donc ecartlon=x/(111120*cos(lat))

    on en déduit:
    • latmin=lat-ecartlat,latmax=lat+ecartlat
    • lonmin=lon-ecartlon,lonmax=lon+ecartlon
    et hop ton carré englobant est défini...avec lat et lon, les coordonnées du point de référence

  6. #6
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut
    hyper intéréssant ! mais je suis pas sur davoir le niveau la..
    Jai peur d'avoir trop à soliciter d'aide pour le mettre en place, il me faudrait un exemple concret(voir une solution lol) !
    Par rapport à ce que tu as dis , je crois avoirs fais la moitié ,
    apres pour mettre ca en format "procédure stockée " ... Ca alair moins précis qu'avec radius mais plus rapide.., à tester..
    Sinon pour la procédure stockée, je suis bien curieuse et intéréssé

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
       SELECT *, 
           ACOS(SIN(RADIANS(48.858484)) * SIN(RADIANS(`lat`)) + 
                COS(RADIANS(48.858484)) * COS(RADIANS(`lat`)) * COS( 
                     RADIANS(`lon`) - RADIANS(2.352849))) * 6371 AS `distance` 
    FROM   (SELECT * 
            FROM   `villes` 
            WHERE  `lat` >= 48.858484 - DEGREES(5 / 6371) 
                   AND `lat` <= 48.858484 + DEGREES(5 / 6371) 
                   AND `lon` >=2.352849 - DEGREES(5/ 6371) / 
                                              COS(RADIANS(48.858484)) 
                   AND `lon` <=2.352849 + DEGREES(5/ 6371) / 
                                              COS(RADIANS(48.858484)) 
           ) AS `jess` 
    HAVING `distance` <=5
    ORDER  BY `distance` ASC

  7. #7
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    having ne doit être utilisé que pour restreindre un group by

    avec les distance en km ça devrait donner ça:
    Code sql : 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
    25
    26
    delimiter $$
    drop function if exists dist_ville$$
    create function dist_ville(la double,lo double,ca double,sa double,ro double)
    returns double
    begin
    	declare rla double default RADIANS(la);
    	return ACOS(sa * SIN(rla) + ca * COS(rla) * COS(RADIANS(lo) - ro)) * 6371;
    end$$
    drop procedure if exists recherche_villes$$
    create procedure recherche_villes(in nomVille varchar(255),in rayon double)
    begin
    	declare latville,lonville,eclo,ecla,lo,la,minla,maxla,minlo,maxlo,cla,sla double;
    	select lat,lon into latville,lonville from villes where nom=nomVille;
    	set lo=radians(lonville),la=radians(latville);
    	set cla=cos(la),sla=sin(la);
    	set eclo=rayon/(11.120*cla),ecla=rayon/11.120;
    	set minla=latville-ecla,maxla=latville+ecla,minlo=lonville-eclo,maxlo=lonville+eclo;
    	select t.nom,t.lat,t.lon,dist_ville(t.lat,t.lon,cla,sla,lo)
    	from
    		(select nom,lat,lon
    		from villes
    		where lat between minla and maxla
    			and lon between minlo and maxlo) t
    	where dist_ville(t.lat,t.lon,cla,sla,lo)<=rayon;
    end$$
    delimiter ;

    pour l'appeler:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    call recherche_villes('Paris',25);

  8. #8
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut
    énorme Ca sent la gestion.., maintenant je vais bucher tout ca
    et je reviens bien sur !
    merci beaucoup

    edit:jai osée te mp jespere ne pas me faire fouéttée

  9. #9
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    non ça va bien que je suis pas sur que tu n'es pas aimé ça hein?

    j'ai rectifié le code, j'avais mis "defaut" au lieu de "default"

  10. #10
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut
    Hello,

    En ajoutant ton code tel quel j'ai une erreure syntaxique " near 'end' at line 16 "
    Jutilise phpmyadmin 3.2.1 avec mysql 5.1.4 , au cas ou..
    Au dela de ça, je pensais (naivement?) qu'on pouvait utiliser une procédure stockée comme un fragment d'une autre requete. Je m'explique,
    mon objectif de base étant de précalculer la requete de distance qui est lourde
    et de stocker son résultat dans une table temporaire . Dans mon site jai besoin d'une requete qui liste tous les éleves dans un rayons x de x villes, je pensais
    donc une fois la procédure stockée créee, pouvoir lutiliser de la sorte :
    ma requete classique sql select 'mes éleves' where 'moyenne>15' and 'LA fameuse procédure stockée'(filtre distance) !
    Je précise que je saurai faire cette requete en SQL habituel ,mais si optimisation possible il y a , optimisation tu devra ..
    Les proczdures stockées cest relativement nouveau, hyper intéréssant mais on se blesse vite avec

  11. #11
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    seules les dernières versions de phpmyadmin permettent d'exécuter les procédures stockées, leur création reste possible tout le temps néanmoins...
    je viens de voir que j'ai oublié un ; à la dernière ligne du corps de la procédure

    sinon je vais supposer que tu as la table eleves(nom,note,idville)

    le code devient:
    Code sql : 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
    25
    26
    27
    delimiter $$
    DROP FUNCTION IF EXISTS dist_ville$$
    CREATE FUNCTION dist_ville(la double,lo double,ca double,sa double,ro double)
    returns double
    begin
    	declare rla double DEFAULT RADIANS(la);
    	RETURN ACOS(sa * SIN(rla) + ca * COS(rla) * COS(RADIANS(lo) - ro)) * 6371;
    end$$
    DROP procedure IF EXISTS recherche_villes$$
    CREATE procedure recherche_villes(IN nomVille varchar(255),IN rayon double,IN notemin double)
    begin
    	declare latville,lonville,eclo,ecla,lo,la,minla,maxla,minlo,maxlo,cla,sla double;
    	SELECT lat,lon INTO latville,lonville FROM villes WHERE nom=nomVille;
    	SET lo=radians(lonville),la=radians(latville);
    	SET cla=cos(la),sla=sin(la);
    	SET eclo=rayon/(11.120*cla),ecla=rayon/11.120;
    	SET minla=latville-ecla,maxla=latville+ecla,minlo=lonville-eclo,maxlo=lonville+eclo;
    	SELECT t.nomeleve,t.note,t.nomville,t.lat,t.lon,dist_ville(t.lat,t.lon,cla,sla,lo)
    	FROM
    		(SELECT e.nom as `nomeleve`,e.note as `note`,v.nom as `nomville`,v.lat as `lat`,v.lon as `lon`
    		FROM villes v
    		inner join eleves e on e.idville=v.id and e.note>=notemin
    		WHERE lat BETWEEN minla AND maxla
    			AND lon BETWEEN minlo AND maxlo) t
    	WHERE dist_ville(t.lat,t.lon,cla,sla,lo)<=rayon;
    end$$
    delimiter ;

    il vaut toujours mieux enregistrer ça dans un fichier .sql, plus facile à manipuler/modifier dans un éditeur avec coloration syntaxique
    à toi d'adapter l'inner join à ta table eleves

    l'appel pour une recherche de tous les élèves à 25km à la ronde de paris avec une note >=15 devient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    call recherche_villes('Paris',25,15);
    pas besoin de select, il est fait dans la procédure...

    ci-joint mon cours sur le procédural
    Images attachées Images attachées

  12. #12
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut
    Bon tout dabord, jai(enfin) réussi à faire fonctionner une procédure stockée() , merci eric69

    Maintenant, jai enfin pu tester la différence de "réaction" des 2 requetes(celle de base) et celle stockée .
    Jai rencontré un avantage et quelques inconvénients avec les procédure stockée ( qui vienne peut etre de moi) , prenons l'exemple 1 comme référence :
    Code sql : 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
    25
    26
    delimiter $$
    DROP FUNCTION IF EXISTS dist_ville$$
    CREATE FUNCTION dist_ville(la double,lo double,ca double,sa double,ro double)
    returns double
    begin
    	declare rla double DEFAULT RADIANS(la);
    	RETURN ACOS(sa * SIN(rla) + ca * COS(rla) * COS(RADIANS(lo) - ro)) * 6371;
    end$$
    DROP procedure IF EXISTS recherche_villes$$
    CREATE procedure recherche_villes(IN nomVille varchar(255),IN rayon double)
    begin
    	declare latville,lonville,eclo,ecla,lo,la,minla,maxla,minlo,maxlo,cla,sla double;
    	SELECT lat,lon INTO latville,lonville FROM villes WHERE nom=nomVille;
    	SET lo=radians(lonville),la=radians(latville);
    	SET cla=cos(la),sla=sin(la);
    	SET eclo=rayon/(11.120*cla),ecla=rayon/11.120;
    	SET minla=latville-ecla,maxla=latville+ecla,minlo=lonville-eclo,maxlo=lonville+eclo;
    	SELECT t.nom,t.lat,t.lon,dist_ville(t.lat,t.lon,cla,sla,lo)
    	FROM
    		(SELECT nom,lat,lon
    		FROM villes
    		WHERE lat BETWEEN minla AND maxla
    			AND lon BETWEEN minlo AND maxlo) t
    	WHERE dist_ville(t.lat,t.lon,cla,sla,lo)<=rayon;
    end$$
    delimiter ;

    Du à l'imbrication (format)de la requete, je n'ai pas réussi a retourné uniquement que dist_ville et un ORDER BY dist_ville n'à pas fonctionner.. Es ce du à moi ou es ce une limitation du faite que la requete soit stockée et/ou imbriquée..?!

    Autre probleme/question, la procédure stockée semble ne pas utiliser
    les 2 index que jai placée dans table villes sur lat et lon , et ne semble pas bénéficier d'un cash contrairement a ce que je lis ici dans lexellent cours d'éric69:

    " La compilation des routines se fait lors du premier appel lors d'une session (connexion) et est mise en cache. Cela
    suit ce qui est fait pour les requêtes... Ce système favorise donc les appels multiples qui se verront donc accélérés
    à partir du deuxième."
    La requete stockée semble consommer beaucoup de ressource à mon phpmyadmin qui se met vite à ramer .
    Je précise que Jai éfféctué tout mes test directement dans phpmyadmin 3.5.8 avec mysql 5.5.30(soit les dernieres versions) ,
    En comparant la requette de base qui est celle ci :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT nom, 
           ACOS(SIN(RADIANS(48.858484)) * SIN(RADIANS(`lat`)) + 
                COS(RADIANS(48.858484)) * COS(RADIANS(`lat`)) * COS( 
                     RADIANS(`lon`) - RADIANS(2.352849))) * 6371 AS `distance` 
    FROM   (SELECT * 
            FROM   `villes` 
            WHERE  `lat` >= 48.858484 - DEGREES(5 / 6371) 
                   AND `lat` <= 48.858484 + DEGREES(5 / 6371) 
                   AND `lon` >=2.352849 - DEGREES(5/ 6371) / 
                                              COS(RADIANS(48.858484)) 
                   AND `lon` <=2.352849 + DEGREES(5/ 6371) / 
                                              COS(RADIANS(48.858484)) 
           ) AS `jess` 
    HAVING `distance` <=5
    ORDER  BY `distance` ASC

    et

    la requete stockée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    call recherche_villes('Paris',25);
    ,

    Avec les meme parametre de requete, soit une recherche à 600km de paris(la base villes contenant 40K lignes) , il s'est avéré que la requete stockée est 33% plus rapide que la requete de base sur une premiere execution
    mais 99% plus longue sur une deuxieme exécution, d'ou le pb de cache que je me pose..
    Ma requete de base se rééxécute quasi instantanément et semble utiliser les index( ?! ), la requete stockée met toujours le meme temps déxécution,et semble consommer beaucoup de ram( ?!)

    Bon..désolé pour la grosseur du post mais le feedback de toutes ces questions me semblent tout aussi important que la question premiere !!

  13. #13
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    tu sais que si tu mets 600km de rayon ça fait 1200km de diamètre de recherche soit là hauteur de la France!!! autant dire que tu cherches dans les 36000 communes donc forcément ça prend de la place en mémoire

    ensuite il te suffit de rajouter le order by dans la procédure stockée sur la requête externe et de ne mettre que ce que tu veux dans la partie affichage du select... ou est ton problème? faut bien sur réécrire et ré-exécuter le contenu du source que je t'ai donné...

    phpmyadmin est un outil d'administration, pas vraiment de test, utilises la console mysql ou mieux un outil comme heidisql quand tu testes en local sur ta machine, ça évite des surprises...

    je vais encore te le redire ta requête marche à cause du fait que mysql est trop souple sur les group by et leur omission... en plus les calculs dans ta requête internes sont...faux

    si tu veux tester si tes index sont utilisés il faut faire un explain sur la grosse requête (pas sur la procédure stockée en entier ça n'aurait aucun sens) dans la procédure en remplaçant les variables par des valeurs...

    pour une même connexion, le temps d'exécution peut s'améliorer vu que tu recompiles pas sinon le temps d'exécution ne change pas...
    après une requête est une requête donc pour comparer il faut déjà générer exactement le même jeu de données

  14. #14
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut
    Oui jai lancé des test sur des grandes quantité pour bien comparé les temps d'éxécution ; Bon pour le select jétais aveugle efféctivement, mais pour le order by, tel qu'est codé la requete, tu ne me fera pas croire que cest possible Jai éssayer dle placé dans toute les positions possible !(il me dit unknow colone dist_ville )essaie !
    Bon jai bien compris que ma requete de base n'est pas académique voir fausse , mais pourquoi fausse outre le "having" ?! Je calcule dans un carré aulieu de calculer dans un rond , jai fais une erreure?!
    Bon mais mise à part ca, jaimerai vraiment mieux comprendre pourquoi la requete stockée ne va pas plus vite apres rééxécution alors que la requete de base (ma requete fausse) rend les résultat quasi instantanné à la rééxécution.
    Ca jaimerai comprendre totalement le pourquoi du comment, ca reste flou.
    Bon, maintenant jai pas encore fait de test en live avec mysqli , pense tu que ca puisse améliorer la vitesse de la requete sstockée?!..

  15. #15
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    si tu calcules pas dans le même carré que moi tu compares quoi?

    le group by ou le order se font sur des noms de colonnes ou à défaut la formule complète du contenu quand y en a pas...
    donc:
    Code sql : 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
    25
    26
    27
    28
    29
    delimiter $$
    DROP FUNCTION IF EXISTS dist_ville$$
    CREATE FUNCTION dist_ville(la double,lo double,ca double,sa double,ro double)
    returns double
    begin
    	declare rla double DEFAULT RADIANS(la);
    	RETURN ACOS(sa * SIN(rla) + ca * COS(rla) * COS(RADIANS(lo) - ro)) * 6371;
    end$$
    DROP procedure IF EXISTS recherche_villes$$
    CREATE procedure recherche_villes(IN nomVille varchar(255),IN rayon double,IN notemin double)
    begin
    	declare latville,lonville,eclo,ecla,lo,la,minla,maxla,minlo,maxlo,cla,sla double;
    	SELECT lat,lon INTO latville,lonville FROM villes WHERE nom=nomVille;
    	SET lo=radians(lonville),la=radians(latville);
    	SET cla=cos(la),sla=sin(la);
    	SET eclo=rayon/(11.120*cla),ecla=rayon/11.120;
    	SET minla=latville-ecla,maxla=latville+ecla,minlo=lonville-eclo,maxlo=lonville+eclo;
    	SELECT t.nomeleve,t.note,t.nomville,t.lat,t.lon,dist_ville(t.lat,t.lon,cla,sla,lo) as dist
    	FROM
    		(SELECT e.nom AS `nomeleve`,e.note AS `note`,v.nom AS `nomville`,v.lat AS `lat`,v.lon AS `lon`
    		FROM villes v
    		INNER JOIN eleves e ON e.idville=v.id AND e.note>=notemin
    		WHERE lat BETWEEN minla AND maxla
    			AND lon BETWEEN minlo AND maxlo) t
    	WHERE dist_ville(t.lat,t.lon,cla,sla,lo)<=rayon
    	order by dist desc;
    end$$
    delimiter ;
    -- pour être sur que ca te prenne bien le dernier delimiter

    pour le coté faux:
    ça sort d'où?? y a pas que le français où tu as du mal, les maths un peu aussi non?

  16. #16
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut
    lol mais tu ne réponds pas a la question : pourquoi la requete stockée ne va pas plus vite à la rééxécution !?
    les math ca va.. le 5 correspond à un demi coté du carré en km , tu as testé la requete ?! car elle est assez précise chez moi..
    effectivement avec l'alias le order by marche forcément mieux
    Teste ma requette fausse en vrai omoins ! on dirait moi a critiquer sans avoir essayer lol

  17. #17
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    tu appliques une fonction pour transformer (des radians en degrés je suppose) à des angles en... degrés...

    1m=1/40000000 de la longueur d'un méridien d'où l'une des approximations en km:
    donc pour toi:

    au moins comme ça tu pars sur les même valeurs dans la requête interne...

    les index ne seront utilisés que dans la requête interne car on utilise des opérateurs (between...and)...
    dés que tu utilises des fonctions, jamais ça les utilise jamais... d'où l'idée de la requête interne qui vient présélectionner les lignes où tu appliques la fonction ou le calcul avec les fonctions trigonométriques...
    teste dans la console mysql pas dans phpmyadmin...

    de plus moi j'ai l'inner join pour sélectionner les ville où les élèves ont la note voulue pas toi dans ta requête...

    j'ai pas tes tables je risque pas de tester...

    encore une fois si tu veux vraiment comparer tu dois comparer exactement la même chose en terme de traitement...

  18. #18
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut
    bon ok je repars testé avec les memes valeurs et dans d'autres conditions
    que phpmyadmin !

  19. #19
    Membre Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    bon alors j'ai testé de mon coté:
    Code sql : 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
    CREATE DEFINER=`root`@`localhost` PROCEDURE `recherche_villes`(IN `nomVille` VARCHAR(255), IN `rayon` DOUBLE, IN `notemin` DOUBLE)
    begin
    	declare latville,lonville,eclo,ecla,lo,la,minla,maxla,minlo,maxlo,cla,sla double;
    	SELECT lat,lon INTO latville,lonville FROM villes WHERE nom=nomVille;
    	SET lo=radians(lonville),la=radians(latville);
    	SET cla=cos(la),sla=sin(la);
    	SET eclo=rayon/(11.120*cla),ecla=rayon/11.120;
    	SET minla=latville-ecla,maxla=latville+ecla,minlo=lonville-eclo,maxlo=lonville+eclo;
    	SELECT t.nomeleve,t.note,dist_ville(t.lat,t.lon,cla,sla,lo)AS dist
    	FROM
    		(SELECT e.nom AS `nomeleve`,e.note AS `note`,v.nom AS `nomville`,v.lat AS `lat`,v.lon AS `lon`
    		FROM villes v
    		INNER JOIN eleves e ON e.idville=v.code_insee AND e.note>=notemin
    		WHERE lat BETWEEN minla AND maxla
    			AND lon BETWEEN minlo AND maxlo) t
    	WHERE dist_ville(t.lat,t.lon,cla,sla,lo)<=rayon   ORDER BY dist ASC LIMIT 500;
    end$$
    0.015 à 0.016s quelque soit la distance (600 ou 15km)...

    déjà une première erreur de ta part: dans la table élèves c'est le code_insee de la table ville donc j'ai rectifié et là ça calcule les vraies distances

    ensuite plein d'élèves n'ont pas de villes sur les 59429 donc ils sont automatiquement exclus...

    ta requête corrigée pour 15km:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT jess.nom, 
           ACOS(SIN(RADIANS(48.858484)) * SIN(RADIANS(`lat`)) + 
                COS(RADIANS(48.858484)) * COS(RADIANS(`lat`)) * COS( 
                     RADIANS(`lon`) - RADIANS(2.352849))) * 6371 AS `distance` 
    FROM   (SELECT v.nom,v.lat,v.lon 
            FROM   villes v
            inner join eleves e
    		  		on v.code_insee=e.idville and e.note>=15
            WHERE  `lat` >= 48.858484 - 15/11.12 
                   AND `lat` <= 48.858484 + 15/11.12 
                   AND `lon` >=2.352849 - 15/11.12 / COS(RADIANS(48.858484)) 
                   AND `lon` <=2.352849 + 15/11.12 / COS(RADIANS(48.858484)) 
           ) AS `jess` 
    HAVING `distance` <=15
    ORDER  BY `distance` ASC;
    0.390s à chaque tentative

    ta requête changée pour 600km:
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT jess.nom, 
           ACOS(SIN(RADIANS(48.858484)) * SIN(RADIANS(`lat`)) + 
                COS(RADIANS(48.858484)) * COS(RADIANS(`lat`)) * COS( 
                     RADIANS(`lon`) - RADIANS(2.352849))) * 6371 AS `distance` 
    FROM   (SELECT v.nom,v.lat,v.lon 
            FROM   villes v
            inner join eleves e
    		  		on v.code_insee=e.idville and e.note>=15
            WHERE  `lat` >= 48.858484 - 600/11.12 
                   AND `lat` <= 48.858484 + 600/11.12 
                   AND `lon` >=2.352849 - 600/11.12 / COS(RADIANS(48.858484)) 
                   AND `lon` <=2.352849 + 600/11.12 / COS(RADIANS(48.858484)) 
           ) AS `jess` 
    HAVING `distance` <=600
    ORDER  BY `distance` ASC;
    0.421s à chaque tentatives

    à noter que de toute façon seule la distance joue vu que tu n'as que des notes à 18 dans ta table élèves...

    la vrai requête que tu devrais construire pour 600km est:
    Code sql : 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
    SELECT jess.nom, 
           ACOS(SIN(RADIANS(48.858484)) * SIN(RADIANS(`lat`)) + 
                COS(RADIANS(48.858484)) * COS(RADIANS(`lat`)) * COS( 
                     RADIANS(`lon`) - RADIANS(2.352849))) * 6371 AS `distance` 
    FROM   (SELECT v.nom,v.lat,v.lon 
            FROM   villes v
            inner join eleves e
    		  		on v.code_insee=e.idville and e.note>=15
            WHERE  `lat` >= 48.858484 - 600/11.12 
                   AND `lat` <= 48.858484 + 600/11.12 
                   AND `lon` >=2.352849 - 600/11.12 / COS(RADIANS(48.858484)) 
                   AND `lon` <=2.352849 + 600/11.12 / COS(RADIANS(48.858484)) 
           ) AS `jess` 
    where ACOS(SIN(RADIANS(48.858484)) * SIN(RADIANS(`lat`)) + 
                COS(RADIANS(48.858484)) * COS(RADIANS(`lat`)) * COS( 
                     RADIANS(`lon`) - RADIANS(2.352849))) * 6371 <=600
    ORDER  BY `distance` ASC;
    temps d'exécution moyen: 0.405s

    je rappelle que toutes les mesures de temps sont aléatoires car dépendant de la charge du serveur (ou de ton ordi) au moment du test... on devrait faire la moyenne de dizaines d'essais pour avoir une valeur significative...

  20. #20
    Membre averti
    Femme Profil pro
    Inscrit en
    Décembre 2012
    Messages
    45
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2012
    Messages : 45
    Par défaut
    Alors,
    d'après mes test en local, la recherche s'avere plus rapide avec la procédure
    stockée. Mais en local, du moins sur mon ordi ,pas de contrainte de ram..
    Les test sur mon serveur non dédié(semi) donc limitté ont montré que la requête stockée était plus lente, la charge serveur étant surement trop grande
    pour ce qu'il m' ai allouée, tres étonnamment tt de meme car il m'est allouée 512 mo de RAM ,et je ne vois pas en quoi cela puisse t'etre insufisant sachant que rien est en production, donc les ressources sont pleines..Peut etre d'autre limitations cachées..
    encore merci

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Table temporaire
    Par Tapioca dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 29/07/2004, 11h32
  2. Table temporaire et résultat requête
    Par Royd938 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 27/07/2004, 14h24
  3. Suppression table temporaire...
    Par Royd938 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 27/07/2004, 12h00
  4. [procédure stockée] table temporaire commençant par #???
    Par franculo_caoulene dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 23/04/2004, 12h23
  5. Nettoyage de table temporaire
    Par Alain Dionne dans le forum Bases de données
    Réponses: 5
    Dernier message: 28/02/2004, 20h44

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