2010-12-07 49 views
1

Existe-t-il une sorte d'optimisation côté serveur (comme dans une base de données MySQL) qui permet à une requête préparée par un utilisateur de bénéficier de la requête précédemment préparée par un autre utilisateur? (L'accent est mis sur les améliorations possibles de performance entre les utilisateurs, chaque requête au cours d'un script php séparé.)Instructions préparées PHP/MySQL - Un utilisateur peut-il bénéficier de la requête préparée par un autre utilisateur?

Exemple:

requête pour l'utilisateur 1: SELECT * FROM SomeTable OÙ item1 =? et item2 =?

article 1 = x 2 = article y

requête pour l'utilisateur 2: SELECT * FROM SomeTable OÙ item1 =? et item2 =? (Même requête comme ci-dessus)

article 1 = y article 2 = z

Si cette requête préparée identique (mais avec des paramètres différents à chaque fois) ne sera exécutée une fois pour chacun de ces différents utilisateurs, est-il un gain de performance potentiel de l'utilisation d'une requête préparée?

Ou serait-il préférable d'utiliser la fonction real_escape_string sur les éléments 1 et 2, et de les placer dans la requête. Cela éviterait d'effectuer deux déplacements sur la base de données, l'un pour vérifier la validité de la requête préparée et l'autre pour exécuter la requête.

Je ne suis pas si inquiet à propos de l'injection SQL, car avec l'échappement approprié, l'une ou l'autre méthode devrait être tout aussi sûre. (Droit?) Je me demande honnêtement si cela vaut la peine d'utiliser des instructions préparées si je ne répète pas l'exécution de la même requête préparée plusieurs fois dans le même script php.

Merci!

Répondre

1

Cela dépend de la version de MySQL que vous utilisez. Voir cette page: http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html Si vous utilisez MySQL avant la version 5.1.17, les instructions préparées ne seront pas mises en cache, et l'utilisation du cache de requêtes MySQL donne de meilleurs résultats que l'utilisation d'instructions préparées, vous devriez donc vous soucier de savoir si vous utilisez ce cache de manière optimisée ou non. Sinon, je pense que la réponse à votre question est oui, car au lieu de le faire deux fois:

  1. envoyer la demande au serveur
  2. compiler la demande
  3. plan d'exécution
  4. exécuter la demande
  5. résultat renvoyez

vous devez faire cela:

préparer:

  1. envoyer la requête au serveur
  2. compiler la demande
  3. plan d'exécution
  4. stocker la demande compilé dans la mémoire
  5. de retour d'un identificateur de requête

EXÉCUTER avec la première série de paramètres:

  1. demander l'exécution avec l'identifiant
  2. exécuter
  3. return result

EXECUTE une autre série de paramètres: 1. demander l'exécution avec l'identifiant 2. exécuter 3. Résultat de retour

(tout cela a été traduit de this french course on prepared statements) Comme vous le voyez, vous aurez un réel gain de performance si:

  • vous exécutez cette demande beaucoup
  • la demande est complexe et prend du temps pour compiler
  • le cache de requête est utilisé
+0

Wow! C'est génial! Je vous remercie! (Et j'utilise une version de MySQL supérieure à 5.1.17) – hithere

+0

Bonus: Si vous voulez optimiser votre MySQL, vous pouvez utiliser ce script: http://mysqltuner.pl Il va analyser le tas de variables disponibles avec ' montrez les variables pour vous et donnez de bons conseils sur ce qui devrait être changé. – greg0ire

0

Le problème ici est que vos deux instances ne peuvent partager aucun code (sans y mettre beaucoup d'efforts). Préparer la requête deux fois devrait être négligeable. S'il y a des goulots d'étranglement de performance, le problème est probablement autre chose.

+0

Mais savez-vous si mon db MySQL ne importe quel type de prêt requête cache qui ferait aller, "Oh, je viens de voir cette déclaration préparée il ya un petit moment! Je peux optimiser cela! "Ou quelque chose comme ça? – hithere

+0

Et cela signifie-t-il que je ferais mieux de ne pas utiliser une instruction préparée pour les types de requêtes dans mon exemple? – hithere

+0

@hithere: Non, je ne sais pas si MySQL met en cache ceci, mais il est probablement assez intelligent pour mettre en cache des choses qui sont pertinentes pour la performance.Je préférerais des instructions préparées sur des requêtes natives, car il est impossible d'ouvrir vos portes pour des injections SQL (accidentellement). – jwueller

1

vous pouvez toujours appeler une procédure stockée - il est juste un seul appel :)

drop procedure if exists get_user; 
delimiter # 

create procedure get_user 
(
in p_user_id int unsigned 
) 
proc_main:begin 
    select u.* from users u where u.user_id = p_user_id; 
end proc_main# 

delimiter ; 

call get_user(1); 
call get_user(3); 
call get_user(6); 
+0

Je ne suis pas du tout familier avec les procédures stockées. On dirait que j'ai d'autres lectures à faire. :) Merci pour la suggestion! – hithere