Optimiser les requêtes Laravel : la bonne façon de regrouper les données

王林
Libérer: 2024-09-09 06:31:38
original
784 Les gens l'ont consulté

Optimizing Laravel Queries: The Right Way to Chunk Data

Pourquoi devriez-vous éviter d’utiliser chunk ?

Il est préférable d'utiliser chunkById au lieu de chunk pour éviter de manquer des lignes lors des mises à jour par lots. L'utilisation de chunk peut décaler le décalage des requêtes suivantes après la mise à jour des lignes, entraînant l'omission des lignes non traitées.

Par exemple :

Post::where('processed', 0)->chunk(100, function($posts) {
    foreach($posts as $post) {
       $post->processed = 1;
       $post->save();
    }
});
Copier après la connexion

Le code ci-dessus génère les requêtes suivantes.

select * from `posts` where `processed` = 0 limit 100 offset 0
select * from `posts` where `processed` = 0 limit 100 offset 100
...
Copier après la connexion

Le premier morceau met à jour 100 lignes. La deuxième requête, l'ignorant, ignore 100 lignes non traitées car elle utilise toujours le décalage.

Ce qui précède est expliqué en détail par
Thai Nguyen Hung

Comment fragmenter un nombre limité de lignes ?

Lorsque nous essayons de traiter un nombre limité de lignes à l'aide de la méthode chunk() de Laravel, nous pouvons nous attendre à ce que le code suivant ne traite que 5 utilisateurs par lots de 2 :

$query  = \App\Models\User::query()->take(5);

$query->chunk(2, function ($users) {
  // Process users
});
Copier après la connexion

Cependant, cela traitera tous les utilisateurs de la base de données, deux à la fois. Cela se produit parce que la méthode chunk() de Laravel ignore la limite take() appliquée à la requête, ce qui entraîne le traitement de toutes les lignes en morceaux.

Pour garantir que seul un nombre limité de lignes (par exemple, 5 utilisateurs) sont traitées en morceaux, nous pouvons implémenter un compteur d'index personnalisé qui brisera la boucle de segmentation après avoir atteint la limite spécifiée. Le code suivant y parvient :

class UserProcessor
{
    private int $index = 0;
    private int $limit = 5;

    public function process()
    {
        $query = \App\Models\User::query();

        $query->chunk(2, function ($users) {
            foreach ($users as $user) {
                $this->index++;

                // Process each user here
                // Example: $user->processData();

                if ($this->index >= $this->limit) {
                    // Stop processing after reaching the limit
                    return false;  // This will stop chunking
                }
            }
        });
    }
}
Copier après la connexion

Remarque

Les $index et $limit sont des propriétés de la classe, pas des variables de méthode transmises à la fermeture avec use($index, $limit). En effet, les variables transmises via use() sont copiées dans l'objet de fermeture par valeur. Par conséquent, toute modification à l'intérieur de la fermeture n'affectera pas les valeurs d'origine, c'est pourquoi elles doivent être des propriétés de classe pour être correctement mises à jour et suivre les modifications au fil des itérations.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal