2011-10-29 2 views
0

Un des avantages des procédures stockées est une bonne vitesse. J'ai fait des tests et obtenu des résultats étranges!Les procédures stockées simples sont plus lentes que les requêtes standard! Pourquoi?

Scénario: Il existe 2 tables, agents et sociétés InnoDB. Chaque agent est lié à une entreprise via FK et indexé sont corrects. S'il vous plaît examiner les moyens ci-dessous:

Deux requêtes simples:

$agent = $pdo->query("SELECT * FROM agents WHERE id=3")->fetch(PDO::FETCH_ASSOC); 
$company = $pdo->query("SELECT name FROM companies WHERE id='$agent[company]'")->fetch(PDO::FETCH_ASSOC); 
$name = $company['name']; 
// 0.000793933868408 
// 0.000741958618164 

Une requête avec JOIN

$agent = $pdo->query(" 
    SELECT agents.*, companies.name FROM agents 
    LEFT JOIN companies ON companies.id=agents.company 
    WHERE agents.id=3 
")->fetch(PDO::FETCH_ASSOC); 
$name = $agent['name']; 
// 0.000327110290527 
// 0.00028395652771 

Deux SP appelle:

$agent = $pdo->query("CALL agents('3')")->fetch(PDO::FETCH_ASSOC); 
$partner = $pdo->query("CALL companies('$agent[company]')")->fetch(PDO::FETCH_ASSOC); 
$name = $agent['name']; 
// 0.010176897049 
// 0.010200023651 

/* 
CREATE PROCEDURE `agents`(agent INT(10)) 
BEGIN SELECT * FROM agents WHERE id=agent; END 

CREATE PROCEDURE `companies`(company INT(10)) 
BEGIN SELECT * FROM companies WHERE id=company; END 
*/ 

Un appel SP avec JOIN:

$agent = $pdo->query("CALL agents('3')")->fetch(); 
$name = $agent['name']; 
// 0.00241208076477 
// 0.00252604484558 

/* 
CREATE PROCEDURE `agents`(agent INT(10)) 
BEGIN 
    SELECT agents.*, companies.name FROM agents 
    LEFT JOIN companies ON companies.id=agents.company 
    WHERE agents.id=agent; 
END 
*/ 

Comment ces SP simples sont lents comme vous avez vu? L'environnement PDO ou système peut-il le provoquer? Comme je sais SP fonctionne très bien pour les requêtes simples, mais ici .....

S'il vous plaît noter que les temps ci-dessus ont été recopiés après 3 fois en cours d'exécution.

Merci AHHP

Répondre

3

d'abord: les requêtes sont mises en cache. Les exécuter plus d'une fois vous montrera principalement à quelle vitesse MySQL peut récupérer leur résultat précédent du cache. Vous pouvez empêcher cela (un peu) en ajoutant SQL_NO_CACHE après votre mot-clé SElECT.

Ensuite, les procédures stockées sont seulement aussi rapides que le code qu'ils exécutent. Si vous exécutez une requête dans une procédure stockée, elle ne sera jamais plus rapide que la requête. Il s'agit toujours de la même requête, mais avec un surcoût supplémentaire lié à l'exécution de la procédure stockée.

Cela peut sembler plus rapide si vous ne renvoyez pas de données de la procédure stockée. Le résultat de la requête exécutée est envoyé à l'appelant. Si vous ne le faites pas dans la procédure stockée, la vitesse que vous gagnez est simplement due à l'envoi de moins de données.

Ensuite, les requêtes que vous exécutez dans la procédure stockée ne sont pas les mêmes que la requête distincte. Dans la requête séparée, vous entrez la valeur exacte dans la chaîne de requête avant qu'elle ne soit envoyée à MySQL, alors que dans la procédure stockée, vous avez une requête paramétrée où vous placez la valeur en paramètre dans le moteur mysql (bien que ce soit caché un peu par la syntaxe des requêtes appelantes dans un proc stocké, cela signifie que l'appel de cette procédure pour la première fois oblige MySQL à réexécuter cette requête, alors que la version 'constant value' est déjà mise en cache

en conclusion, votre test est faux.

une procédure stockée est plus rapide si vous avez besoin de faire un peu de traitement ou de filtrage qui ne peut être fait dans une seule requête. Récupérer toutes les données à PHP et le traitement là, les causes aussi beaucoup de données à envoyer entre PHP et MySQL. Si vous effectuez tout le traitement dans une procédure stockée et n'envoyez que le résultat (petit), c'est plus rapide, mais surtout parce que tout le traitement reste dans le moteur SQL, donc il n'y a pas de sérialisation/désérialisation ni d'envoi de données.

+0

Merci @GolezTrol pour une réponse détaillée.A propos de la mise en cache, j'ai couru des requêtes plusieurs fois et le résultat est pour les derniers tests donc quereis devait être mis en cache. A propos du 2ème paragraphe, comme je l'ai découvert, SP ne fait des requêtes rapides que via la mise en cache? Au sujet du 3ème paragraphe, pourriez-vous m'expliquer davantage? Utiliser des SP en tant que processeur (ne pas retourner de données, juste faire quelque chose) les rend un peu inutiles! Je n'ai pas compris votre signification. Et au sujet du dernier paragraphe, mon test n'est pas un point de référence. Dans mon test j'ai une variable et je veux obtenir un champ de sa relation. Je cherche à faire de telles tâches de la meilleure façon de ne pas discuter des tests MySQL – AHHP

+0

Le troisième paragraphe se réfère à ce que je dis dans le dernier. Vous pouvez utiliser des procédures stockées pour traiter des données et les renvoyer. Dans votre cas, vous exécutez simplement la requête, renvoyez son résultat, et c'est tout. La procédure stockée doit donc pouvoir s'exécuter au minimum le temps nécessaire à l'exécution de la procédure, car c'est ce qu'elle fait exactement, plus un léger surcoût d'appel de la procédure elle-même. Si l'encapsulation d'une requête comme celle-ci dans une procédure stockée le rendrait plus rapide, tout le monde le ferait. Ou plus probablement, cela serait fait automatiquement par MySQL. :) – GolezTrol

Questions connexes