web-dev-qa-db-ja.com

PDO :: rowCount VS COUNT(*)

私はクエリがPDOを使用していて、行が1より多い場合は最初に行を数えてデータをフェッチします

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

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

    }
}
else{echo "no result";}
_

または

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


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

どちらがパフォーマンスが向上しますか?

2番目。質問、idにインデックスを設定した場合

どちらが優れているかCOUNT(id)またはCOUNT(*)

20
Ben

最初の質問:

Count COUNT()を使用すると、サーバー(MySQL)は内部的にリクエストを異なる方法で処理します。

COUNT()を実行すると、サーバー(MySQL)はカウントの結果を保存するためのメモリのみを割り当てます。

$row=$SQL->rowCount();を使用する場合、サーバー(Apache/PHP)は結果セット全体を処理し、それらすべての結果にメモリを割り当て、サーバーをフェッチモードにします。これにはロックなどのさまざまな詳細が含まれます。

PDOStatement::rowCount()は、返された行の数ではなく、最後のステートメントによって影響を受けた行の数を返すことに注意してください。関連するPDOStatementによって最後に実行されたSQLステートメントがSELECTステートメントであった場合、一部のデータベースはそのステートメントによって返された行数を返す場合があります。ただし、この動作はすべてのデータベースで保証されているわけではなく、ポータブルアプリケーションに依存すべきではありません。

私の分析では、COUNT()を使用すると、プロセスはMySQLとPHPの両方に分割されますが、$row=$SQL->rowCount();を使用すると、処理はPHPの詳細。

したがって、MySQLのCOUNT()は高速です。

2番目の質問:

COUNT(*)COUNT(id)よりも優れています。

説明:

Mysqlのcount(*)関数は、値のカウントを見つけるために最適化されています。ワイルドカードを使用すると、すべての行がフェッチされるわけではありません。カウントのみを検索します。したがって、可能な限りcount(*)を使用してください。

出典:

23
Christian Mark

実際のところ、PDO rowCountもCOUNT(*)もここでは必要ありません。

行> 1の場合、データをフェッチします

誤りのある声明です。
健全に設計されたWebアプリケーション(PHPの冗談のように聞こえますが)では、このようにする必要はありません。
最も賢明な方法は

  • 最初に取得する
  • 取得したデータを使用する
  • 必要に応じて、この非常にフェッチされたデータを使用して、何かが返されたかどうかを確認できます。

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

簡単でわかりやすく、「どの役に立たない機能が優れている」などの質問は一切ありません。

あなたの場合、idが一意のインデックスであると仮定すると、1行のみが返されます。したがって、whileステートメントはまったく必要ありません。上記のスニペットを使用して、enythinを取得したかどうかを取得します。

多くの行が予想される場合は、fetch()fetchAll()に変更し、foreachを使用して、返された配列を繰り返します。

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

必要以上の行を選択しないでください。通常のWebページでのクエリは、表示されるよりも多くの行を返さないことを意味します。

質問自体といえば、それは意味がありません。 rowCount VS COUNT(*)を比較することはできません。これは比較できない問題だからです。これらの2つの機能の目的はまったく異なるため、交換することはできません。

  • COUNT(*)はcountを含む単一の行を返します。レコードのカウントが必要な場合にのみ使用する必要がありますただし、レコード自体はありません
    レコードが必要な場合、count(whatever)は高速でも低速でもありません-無意味
  • rowCount()既に選択されている行の数を返すため、上記のようにほとんど必要ありません。

2番目の例行をまったくフェッチしないは言うまでもありません

14

どちらの場合も1つのクエリのみを発行するため、パフォーマンスの違いはnullに無視できるはずです。 2番目のクエリは、idに一致するすべての行に対して同じ値を持つ追加の列をフェッチする必要があるため、メモリフットプリントが大きくなる可能性があります。 COUNT(*)がなくても行カウントが使用可能である必要があるため、最初のソリューションを使用する必要があります。

2番目の質問については、COUNT(id)またはCOUNT(*)のいずれかがidのインデックスにより高速になります。これは、dbエンジンが取得するために範囲スキャンを実行する必要があるためです。問題の行、および範囲スキャン高速インデックス付き列でフィルタリングする場合、インデックス付き(あなたの場合はid = SOME_ID)。

1
Nikhil

Count(id)またはcount(*)はインデックススキャンを使用するため、パフォーマンスが向上します。行数は影響を受ける行のみを返し、挿入/更新/削除に役立ちます

編集:質問はCount(id)とcount()を比較するために編集されているため、わずかな違いが生じます。 Count()は、selectの影響を受けた行数を返します。 Count(column)はnull以外の値のcountを返しますが、idであるため、null列はありません。したがって、この場合には違いはありません。

1
Kuzgun

Count(*)はより高速になります。

PDOStatement::rowCount()は、PDOドキュメントに従って動作することを保証されていません。

「すべてのデータベースについて保証されているわけではなく、ポータブルアプリケーションに依存すべきではありません。」

そのため、count(*)を使用することをお勧めします。

リファレンスを参照してください: pdostatement.rowcount Manual

1
Moeed Farooqui