web-dev-qa-db-fra.com

PDO :: rowCount VS COUNT (*)

j'ai une requête, utilisez PDO, comptez d'abord la ligne, si la ligne> 1, récupérez les données

SELECT * WHERE id=:id
$row=$SQL->rowCount();

if($row>0){
    while($data=$SQL->fetch(PDO::FETCH_ASSOC)){...

    }
}
else{echo "no result";}

ou

SELECT COUNT(*), * WHERE id=:id
$data=fetch(POD::FETCH_NUM);
$row=data[0];


if($row>0){
//fetch data
}
else{echo "no result";}

Quelles seront les meilleures performances?

2e. question, si j'ai mis en place l'index sur id

lequel est le meilleur COUNT(id) ou COUNT(*)

20
Ben

1ère question:

En utilisant count COUNT(), en interne, le serveur (MySQL) traitera la demande différemment.

Lorsque vous faites COUNT(), le serveur (MySQL) alloue uniquement de la mémoire pour stocker le résultat du comptage.

Lorsque vous utilisez $row=$SQL->rowCount();, le serveur (Apache/PHP) traitera l'ensemble des résultats, allouera de la mémoire pour tous ces résultats et mettra le serveur en mode de récupération, ce qui implique de nombreux détails différents, tels que le verrouillage.

Notez que PDOStatement::rowCount() renvoie le nombre de lignes affectées par la dernière instruction, pas le nombre de lignes retournées. Si la dernière instruction SQL exécutée par la PDOStatement associée était une instruction SELECT, certaines bases de données peuvent renvoyer le nombre de lignes renvoyées par cette instruction. Toutefois, ce comportement n'est pas garanti pour toutes les bases de données et ne doit pas être utilisé pour les applications portables.

D'après mon analyse, si vous utilisez COUNT(), le processus serait divisé à la fois en MySQL et PHP tandis que si vous utilisez $row=$SQL->rowCount();, le traitement serait plus pour PHP.

Par conséquent, COUNT() dans MySQL est plus rapide.

2ème question:

COUNT(*) est mieux que COUNT(id).

Explication:

La fonction count(*) dans mysql est optimisée pour trouver le nombre de valeurs. L'utilisation de caractères génériques signifie qu'elle ne récupère pas chaque ligne. Il ne trouve que le comte. Utilisez donc count(*) dans la mesure du possible.

Sources:

23
Christian Mark

En fait, ni PDO rowCount ni COUNT (*) ne sont jamais requis ici.

si ligne> 1, récupérer les données

est une déclaration défectueuse.
Dans une application Web bien conçue (je sais que cela ressemble à une blague pour PHP), il n'est pas nécessaire de procéder de cette façon.
Le moyen le plus sensé serait

  • aller chercher en premier
  • d'utiliser les données extraites
  • si nécessaire, nous pouvons utiliser ces données très récupérées pour voir si quelque chose a été retourné:

    $data = $stmt->fetch();
    if($data){
        //use it whatever
    } else {
        echo "No record";
    }
    

Facile, simple et sans aucune question comme "quelle fonctionnalité inutile est la meilleure" du tout.

Dans votre cas, en supposant que id est un index unique, une seule ligne peut être renvoyée. Par conséquent, vous n'avez absolument pas besoin de l'instruction while. Utilisez simplement l'extrait ci-dessus pour récupérer et pour dire si enythin a été récupéré.

Dans le cas où de nombreuses lignes sont attendues, changez simplement fetch() en fetchAll() puis utilisez foreach pour itérer le tableau renvoyé:

$data = $stmt->fetchAll();
if($data){
    foreach ($data as $row) {
        //use it whatever
    }
} else {
    echo "No records";
}

Notez que vous ne devez jamais sélectionner plus de lignes que nécessaire. signifie que votre requête sur une page Web standard ne doit jamais renvoyer plus de lignes que celles qui seront affichées.

En parlant de la question elle-même - cela n'a aucun sens. On ne peut pas comparer rowCount VS COUNT(*), parce que c'est incomparable. Ces deux fonctions ont un objectif absolument différent et ne peuvent pas être échangées:

  • COUNT(*) renvoie une seule ligne avec count, et doit être utilisée UNIQUEMENT si l'on a besoin du nombre d'enregistrements, mais pas d'enregistrements eux-mêmes.
    si vous avez besoin des enregistrements, count(whatever) n'est ni plus rapide ni plus lent - c'est inutile
  • rowCount() renvoie le nombre de lignes déjà sélectionnées et donc vous en avez à peine besoin, comme cela a été montré ci-dessus.

Sans oublier que le deuxième exemple ne récupérera aucune ligne du tout.

14

La différence de performances doit être négligeable ou nulle, car vous n'émettez qu'une seule requête dans les deux cas. La deuxième requête doit récupérer une colonne supplémentaire avec la même valeur pour chaque ligne correspondant à id, par conséquent, elle peut avoir une grande empreinte mémoire. Même sans la COUNT(*) le nombre de lignes devrait être disponible, vous devriez donc opter pour la 1ère solution.

À propos de votre deuxième question, AFAIK soit COUNT(id) ou COUNT(*) sera plus rapide avec l'index sur id, car le moteur de base de données devra effectuer un balayage de plage pour récupérer le lignes en question et analyses de plage sont plus rapides avec des index lors du filtrage sur la colonne indexée (dans votre cas id = SOME_ID).

1
Nikhil

Count (id) ou count (*) utilisera le scan d'index afin d'améliorer les performances. Rowcount renvoie uniquement les lignes affectées et utile lors de l'insertion/mise à jour/suppression

EDIT: Puisque la question a été éditée pour comparer Count (id) et count (), cela fait une légère différence. Count () renverra le nombre de lignes affecté par select. Count (colonne) renverra le nombre de valeurs non nulles mais comme il est id, il n'y aura pas de colonne nulle. Cela ne fait donc aucune différence dans ce cas.

1
Kuzgun

Count(*) sera plus rapide.

PDOStatement::rowCount() n'est pas garanti de fonctionner selon la documentation PDO:

"non garanti pour toutes les bases de données et ne doit pas être utilisé pour les applications portables."

Donc, dans votre cas, je vous suggère d'utiliser count(*).

Voir référence: pdostatement.rowcount Manual

1
Moeed Farooqui