JeuWeb - Crée ton jeu par navigateur
Procédure stockée MYSQL - Version imprimable

+- JeuWeb - Crée ton jeu par navigateur (https://jeuweb.org)
+-- Forum : Discussions, Aide, Ressources... (https://jeuweb.org/forumdisplay.php?fid=38)
+--- Forum : Programmation, infrastructure (https://jeuweb.org/forumdisplay.php?fid=51)
+--- Sujet : Procédure stockée MYSQL (/showthread.php?tid=5485)

Pages : 1 2


RE: Procédure stockée MYSQL - Zack - 15-06-2011

Normalement, une procédure stockée est dans tous les cas plus rapide puisqu'elle est pré-compilé sur le serveur. Donc on transfert beaucoup moins d'informations du client au serveur et le serveur travaille moins du coup puisqu'il n'a pas besoin de la réinterpréter à chaque fois.

Après je ne sais pas combien de millisecondes ça fait gagner par rapport aux autres méthodes et ce serait assez galère de faire les benchmarks, mais depuis que je l'ai mise la charge du serveur a été divisé par 1.5. Donc dans mon cas, c'est bien utile ^^.

Et sinon voici la vrai requête que j'utilise, celle que je donnais c'était juste pour faciliter la vue de mon problème :

SELECT UNIX_TIMESTAMP() as timestamp_, action_, action_lien, sortRecu, typeSortRecu, sortRecuPar, P.idJoueur, pseudo, x, y, 
pvActuel, pvMax, reiatsuActuel, reiatsuMax, niveau, xp, koro, reputation, rang, clan, sexe, shinigami,
humain, transformation, combatEnCours, demandeCombat, etatPersonnage, boostPersonnage, avatarMJ
FROM personnage P
JOIN joueur J
JOIN caracteristique C
on J.idJoueur = P.idJoueur and C.idJoueur = P.idJoueur
WHERE x BETWEEN $minX and $maxX and y BETWEEN $minY and $maxY AND UNIX_TIMESTAMP(derniereActualisation) > (UNIX_TIMESTAMP()-600) AND P.idCarte = 0

Un peu plus compliqué que l'autre, et l'appeler toutes les 2 secondes méritait quand même que je la mette en procédure stockée.

Ensuite est ce que remplacer le BETWEEN par les opérateurs directement est plus rapide ?


RE: Procédure stockée MYSQL - niahoo - 15-06-2011

(15-06-2011, 11:01 AM)Zack a écrit : Ensuite est ce que remplacer le BETWEEN par les opérateurs directement est plus rapide ?

Ben en procédure stockée je suppose que ça revient au même.


RE: Procédure stockée MYSQL - Zack - 15-06-2011

J'ai remplacé le between tout de même. Si ça peut permettre de grappiller un peu ^^

D'ailleurs, je viens de rencontrer un problème après une procédure stockée. Si après la procédure stockée, je fais une modification sur la table que la procédure a utilisé, j'ai une erreur "Commands out of sync; you can't run this command now".

Apparemment, ce serait un problème de libération des ressources ou je ne sais quoi. Sur le site de mysql, ils disent de mettre un mysql_use_result() ou mysql_store_result() mais ces fonctions n'existent pas, elles ne sont pas reconnu pourtant je suis sur du mysql 5.1. Du coup, je comprend pas.

J'ai tenté avec un mysql_free_result mais l'erreur est toujours là.

Quelqu'un a t-il déjà rencontré ce problème ?


RE: Procédure stockée MYSQL - php_addict - 15-06-2011

(15-06-2011, 08:58 PM)Zack a écrit : Apparemment, ce serait un problème de libération des ressources ou je ne sais quoi. Sur le site de mysql, ils disent de mettre un mysql_use_result()

pourtant ces fonctions semblent exister : http://dev.mysql.com/doc/refman/5.0/fr/mysql-use-result.html

elles font partie de l'API C

il te manque des paquets sur ton serveur:

http://www.siteduzero.com/tutoriel-3-34984-utiliser-l-api-mysql-dans-vos-programmes.html


RE: Procédure stockée MYSQL - Jeckel - 20-06-2011

(15-06-2011, 11:01 AM)Zack a écrit : Normalement, une procédure stockée est dans tous les cas plus rapide puisqu'elle est pré-compilé sur le serveur. Donc on transfert beaucoup moins d'informations du client au serveur et le serveur travaille moins du coup puisqu'il n'a pas besoin de la réinterpréter à chaque fois.

Ça c'est pas tout à fait vrai..
La procédure est pré-compilée, mais pas son résultat... Une requête SQL sera pré-compilée aussi avant d'être exécuter, tu ne gagnes donc que le temps de "pré-compilation" du code de la requête, autrement dit, sur une requête de quelques lignes : rien du tout.

La "pré-compilation" d'une procédure stockée dans MySQL n'est d'ailleurs pas du tout présenté comme un avantage, mais comme une contrainte... en effet, le fait que la procédure soit pré-compilé fait que tu ne peux pas avoir de code "variable" dans ta procédure, c'est un dire par exemple exécuter une requête qui soit construite sous la forme d'une concaténation.

(15-06-2011, 11:01 AM)Zack a écrit : Après je ne sais pas combien de millisecondes ça fait gagner par rapport aux autres méthodes et ce serait assez galère de faire les benchmarks, mais depuis que je l'ai mise la charge du serveur a été divisé par 1.5. Donc dans mon cas, c'est bien utile ^^.

Je ne sais pas d'pù vient ton gain de performance, mais cela ne vient pas du faite que la procédure soit "pré-compilée".

(15-06-2011, 11:01 AM)Zack a écrit : Et sinon voici la vrai requête que j'utilise, celle que je donnais c'était juste pour faciliter la vue de mon problème :

SELECT UNIX_TIMESTAMP() as timestamp_, action_, action_lien, sortRecu, typeSortRecu, sortRecuPar, P.idJoueur, pseudo, x, y, 
pvActuel, pvMax, reiatsuActuel, reiatsuMax, niveau, xp, koro, reputation, rang, clan, sexe, shinigami,
humain, transformation, combatEnCours, demandeCombat, etatPersonnage, boostPersonnage, avatarMJ
FROM personnage P
JOIN joueur J
JOIN caracteristique C
on J.idJoueur = P.idJoueur and C.idJoueur = P.idJoueur
WHERE x BETWEEN $minX and $maxX and y BETWEEN $minY and $maxY AND UNIX_TIMESTAMP(derniereActualisation) > (UNIX_TIMESTAMP()-600) AND P.idCarte = 0

Un peu plus compliqué que l'autre, et l'appeler toutes les 2 secondes méritait quand même que je la mette en procédure stockée.

Ensuite est ce que remplacer le BETWEEN par les opérateurs directement est plus rapide ?

Pour optimiser ta requête :
- utiliser des conditions dans te jointures "JOIN ma_table ON condition" ou "JOIN ma_table USING (index)"
- tous les champs dans les conditions doivent être indexé et avoir le même format (comparer un INT avec un INT et non un CHAR(1) par exemple) sinon, MySQL n'utilise tout simplement pas ses tables d'index
- utiliser ces jointures de préférances avec des ET et des =... les OU et autres ne passent pas par les index

Pour schématiser, dans MySQL tous les champs indexés se retrouvent dans un fichier/table à part... lorsque MySQL doit faire une recherche sur les index, il n'a qu'à pointer les lignes avec des index équivalent, ça ne représente donc presque aucun calcul. Si tu mets des OU ou pire des BETWEEN, MySQL est obligé de faire un calcul pour chaque champs, le temps de traitements augmente d'autant.

Ensuite, dans l'ordre MySQL va traiter les éléments de la requête grosso-modo dans l'ordre suivante :
- sélection des lignes dans les jointures de la première à la dernier jointure
- appliquer le WHERE sur le résultat obtenu
- appliquer les GROUP BY et autre HAVING
- appliquer les instructions du SELECT

Pour gagner du temps, il faut que les jointures soient restrictives, c'est à dire qu'elle réduisent le nombre d'enregistrement à traiter par le WHERE et non faire un produit cartésien : dans l'idéal la première table doit contenir le plus grand nombre d'enregistrement, la seconde doit réduire ce nombre de ligne en appliquant la condition de jointure, etc...

Autre remarque, les alias de table, si c'est pour rendre le code illisible, ça ne sert à rien, les alias ne sont vraiment utile que si tu dois avoir plusieurs fois la même table mais pour des jointures différentes...

Je reprend ton exemple :


SELECT UNIX_TIMESTAMP() as timestamp_, action_, action_lien, sortRecu, typeSortRecu, sortRecuPar, P.idJoueur, pseudo, x, y,
pvActuel, pvMax, reiatsuActuel, reiatsuMax, niveau, xp, koro, reputation, rang, clan, sexe, shinigami,
humain, transformation, combatEnCours, demandeCombat, etatPersonnage, boostPersonnage, avatarMJ
FROM personnage
JOIN joueur USING (idJoueur)
JOIN caracteristique USING (idJoueur)
WHERE x BETWEEN $minX and $maxX and y BETWEEN $minY and $maxY AND UNIX_TIMESTAMP(derniereActualisation) > (UNIX_TIMESTAMP()-600) AND P.idCarte = 0

Voilà pour les jointures...
La table "caracteristique" concerne le joueur ou le personnage ?
Si tu veux un peu plus d'aide, il me faut la structure de tes tables et un jeu de données de test


RE: Procédure stockée MYSQL - Zack - 22-06-2011

Et beh, bah merci !
Pas mal de choses que je ne savais pas, j'vais étudier tout ça du coup !

Sinon la table caractéristique concerne le personnage mais le joueur aussi, ils ont tous les 3 la même clé idJoueur. Mais en fait, mes tables sont pas super bien structuré, j'aurai pu faire qu'une table avec joueur et personnage mais j'avais fais ça à mes débuts en croyant bien faire.

Cette structure aurait pu être intéressante si j'en avais profité pour faire en sorte qu'un joueur puisse avoir plusieurs personnages, mais non, j'ai fait ça comme une bouse ^^