AOP:: rowCount VS COUNT(*)

j'ai une requête utiliser PDO, compter la ligne en premier, si la ligne >1 que fetch 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";}

quelle sera la meilleure performance?

2ème. question, si j'ai mis en place l'indice id

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

18
demandé sur Ben 2013-10-01 10:53:07

5 réponses

1ère question:

en utilisant count COUNT(), en interne le serveur(MySQL) traitera la requête différemment.

en faisant COUNT(), le serveur (MySQL) n'allouera de mémoire que pour stocker le résultat du comptage.

en utilisant $row=$SQL->rowCount(); le serveur (Apache/PHP) va traiter l'ensemble des résultats, allouer de la mémoire pour tous ces résultats, et mettre le serveur en mode de récupération, ce qui implique beaucoup de détails différents, tels que verrouillage.

Prendre note que PDOStatement::rowCount() renvoie le nombre de lignes affectées par le dernier relevé, pas le nombre de lignes retournées. Si la dernière instruction SQL exécutée par lePDOStatement est un SELECT déclaration, certaines bases de données peuvent retourner le nombre de lignes retournées par cette déclaration. Toutefois, ce comportement n'est pas garanti pour toutes les bases de données et ne devrait pas être utilisé pour les applications portables.

Sur mon analyse, si vous utilisez COUNT(), le processus serait divisé à la fois MySQL et PHP alors que si vous utilisez $row=$SQL->rowCount();, le traitement serait plus pour PHP.

Donc COUNT() en MySQL est plus rapide.

2e question:

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

Explication:

count(*) la fonction mysql est optimisée pour trouver le nombre de valeurs. Utiliser le caractère sauvage signifie qu'il ne va pas chercher chaque ligne. Il seulement trouver le comte. Donc, utiliser count(*) où possible.

Sources:

23
répondu Christian Mark 2013-10-30 03:32:41

en fait, ni rowCount AOP ni COUNT (*) ne sont nécessaires ici.

si la rangée >1 alors fetch data

est une déclaration erronée.

Dans une application Web conçue par sanely (je sais que cela ressemble à une blague pour PHP), on n'a pas à le faire de cette façon.

La façon la plus raisonnable serait

  • chercher d'abord
  • utiliser le récupéré données
  • 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 pas de questions comme "quelle fonctionnalité inutile est la meilleure".

Dans votre cas, en supposant que id est un index unique, une seule ligne peut être retourné. Par conséquent, vous n'avez pas besoin d' while déclaration du tout. Il suffit d'utiliser l'extrait ci-dessus soit pour aller chercher et pour dire si enythin a été récupéré.

dans le cas où beaucoup de lignes sont attendues, alors changez fetch()fetchAll() puis utilisez foreach pour itérer le tableau retourné:

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

Notez que vous ne devriez jamais sélectionner plus de lignes que nécessaire. Signifie que votre requête sur une page web ne devrait jamais retourner plus de lignes que sera affiché.

en parlant de la question elle - même-cela n'a aucun sens. On ne peut pas comparer rowCount VS COUNT(*), parce que ce sont des choses incomparables. Ces deux fonctions a tout à fait différentes fins et ne sont pas interchangeables:

  • COUNT(*) renvoie une seule ligne avec le nombre, et ne doit être utilisé que si l'on a besoin du nombre d'enregistrements, mais pas les dossiers eux-mêmes.

    si vous avez besoin de les dossiers, count(whatever) n'est pas le plus rapide ni lent -inutile.
  • rowCount() retourne nombre de lignes sélectionnées et donc vous en avez à peine besoin, comme il était indiqué ci-dessus.

sans mentionner que le second exemple va chercher aucune ligne.

14
répondu Your Common Sense 2017-07-31 04:55:08

Count (id) ou count (*) utiliseront l'index scan pour améliorer les performances. Rowcount retourne seulement les lignes affectées et utile sur insert / update / delete

EDIT: Puisque la question a été modifiée pour comparer le nombre (id) et le nombre(), il fait une légère différence. Le comte() retournera le nombre de lignes affecté par select. Count (column) retournera la valeur non nulle count mais puisqu'il s'agit d'id, il n'y aura pas de colonne nulle. Donc, il ne fait pas de différence pour ce cas.

1
répondu Kuzgun 2013-10-01 07:11:41

la différence de Performance devrait être négligeable à null, puisque vous n'émettez qu'une seule requête dans les deux cas. La 2ème requête doit extraire une colonne supplémentaire avec la même valeur pour chaque ligne correspondant à id, donc il pourrait avoir une grande empreinte mémoire. Même sans le COUNT(*) le nombre de rangées doit être disponible, donc vous devez choisir la première solution.

A propos de votre 2e question, AFAIK soit COUNT(id) ou COUNT(*) sera plus rapide avec l'index sur id, depuis le moteur db devra effectuer un balayage de gamme pour récupérer les lignes en question, et balayages de gamme sont plus rapides avec index lors du filtrage sur la colonne indexée (dans votre cas id = SOME_ID).

1
répondu Nikhil 2013-10-01 07:12:36

Count(*) sera plus rapide.

PDOStatement::rowCount() n'est pas garanti pour fonctionner selon l'AOP de la documentation:

" n'est pas garanti pour toutes les bases de données et ne devrait pas être utilisé pour les applications portables."

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

voir référence: pdostatement.manuel rowcount

1
répondu Moeed Farooqui 2014-10-10 21:00:36