25-02-2017, 05:45 PM
Je n'ai pas franchement compris l'exemple, mais le soucis des boucles de requête est réel et double:
• 1000 petites requêtes hors du SQL (dans le PHP) impliquent 1000 accès réseau
• Le SQL n'est pas optimisé pour traiter 1000 petites requêtes, mais plutôt pour traiter 1 grosse requête sur 1000 éléments
Le premier problème peut être très simple à régler, par une procédure stockée (tu passes ton 90 et d'autres éventuelles entrées à la procédure stockée, qui contiendra le WHILE/la boucle de requête). C'est pas optimal, mais c'est généralement très rapide à faire et cela peut patcher un serveur avant qu'il ne se meurt (on dégage alors du temps pour repenser et refactorer proprement le réel problème).
Le second problème se règle par l'intelligence (donc, pas de méthode générale). Comme j'ai pas vraiment compris l'exemple (pour "l'intelligence", c'est rate ^^), je serai peut-être à côté de la réponse, mais il me semble que dans l'idée, tu as 90 passager qui veulent prendre un des avions parmi une liste d'avions possible (ici, 2, qui répondent à une clause genre WHERE avion.id_joueur = ?). Chaque avion a une capacité maximale (avion.capa, ici, 80 et 40 passagers) et éventuellement, il y a déjà des passagers dans l'avion (avion.passagers peut être nul ou positif).
Tu voudrais savoir combien de passagers on a au final dans chaque avion, et éventuellement, le nombre de passagers sans avion.
Je considèrerai qu'il y a une règle d'ordonnancement des avions à remplir (ORDER BY ...)
Jusqu'ici, tu fonctionnes selon (en gros):
Je dirai que cela peut se réécrire sous la forme:
L'idée ici est de calculer, ligne par ligne, le nombre de gens qui prennent l'avion (@dansAvion), de définir que cette valeur est le nombre de passagers de l'avion, et décrémenter cette valeur du nombre total de passagers (@passagers).
Je ne sais pas si on peut esquiver l'astuce du "0*..." pour définir la nouvelle valeur de @passagers. Je suppose qu'on devrait aussi pouvoir optimiser un peu pour que le SQL comprenne qu'il n'a plus besoin de traiter les lignes de la table dès que @passagers est à 0.
• 1000 petites requêtes hors du SQL (dans le PHP) impliquent 1000 accès réseau
• Le SQL n'est pas optimisé pour traiter 1000 petites requêtes, mais plutôt pour traiter 1 grosse requête sur 1000 éléments
Le premier problème peut être très simple à régler, par une procédure stockée (tu passes ton 90 et d'autres éventuelles entrées à la procédure stockée, qui contiendra le WHILE/la boucle de requête). C'est pas optimal, mais c'est généralement très rapide à faire et cela peut patcher un serveur avant qu'il ne se meurt (on dégage alors du temps pour repenser et refactorer proprement le réel problème).
Le second problème se règle par l'intelligence (donc, pas de méthode générale). Comme j'ai pas vraiment compris l'exemple (pour "l'intelligence", c'est rate ^^), je serai peut-être à côté de la réponse, mais il me semble que dans l'idée, tu as 90 passager qui veulent prendre un des avions parmi une liste d'avions possible (ici, 2, qui répondent à une clause genre WHERE avion.id_joueur = ?). Chaque avion a une capacité maximale (avion.capa, ici, 80 et 40 passagers) et éventuellement, il y a déjà des passagers dans l'avion (avion.passagers peut être nul ou positif).
Tu voudrais savoir combien de passagers on a au final dans chaque avion, et éventuellement, le nombre de passagers sans avion.
Je considèrerai qu'il y a une règle d'ordonnancement des avions à remplir (ORDER BY ...)
Jusqu'ici, tu fonctionnes selon (en gros):
Code :
$passagers = 90;
while ($passagers > 0) {
UPDATE avion SET passagers = MIN(capa, $passagers) WHERE avion.id = NEXT_AVION();
$passagers -= avion.capa
}
Je dirai que cela peut se réécrire sous la forme:
SET @passagers := 90;
UPDATE avion
SET passagers = (@dansAvion := LEAST(capa, @passagers)) + 0*(@passagers := @passagers - @dansAvion)
WHERE ...
ORDER BY ...;
SELECT @passagers; -- Passagers sans avion
L'idée ici est de calculer, ligne par ligne, le nombre de gens qui prennent l'avion (@dansAvion), de définir que cette valeur est le nombre de passagers de l'avion, et décrémenter cette valeur du nombre total de passagers (@passagers).
Je ne sais pas si on peut esquiver l'astuce du "0*..." pour définir la nouvelle valeur de @passagers. Je suppose qu'on devrait aussi pouvoir optimiser un peu pour que le SQL comprenne qu'il n'a plus besoin de traiter les lignes de la table dès que @passagers est à 0.