MySQLのCOUNT(*)のパフォーマンスについてお話しましょう

MySQLのCOUNT(*)のパフォーマンスについてお話しましょう

序文

基本的に、職場のプログラマーは、count(*)、count(1)、または count(primary key) を使用して、データベース テーブルの行数をカウントします。これらの違いとパフォーマンスを理解していますか?

実際、開発プロセス中に、プログラマーが大きなテーブル内の行の総数を数えることは、非常に時間のかかる作業です。では、より速く数えるにはどの方法を使用すればよいでしょうか?

次に、MySQL で総行数をカウントする方法とパフォーマンスについて説明します。

count(*)、count(1)、count(主キー)のうちどれが速いでしょうか?

1. テーブルを作成し、実験テスト用に 1,000 万件のレコードを挿入します。

# テストテーブルを作成する CREATE TABLE `t6` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(50) NOT NULL,
 `status` tinyint(4) NOT NULL、
 主キー (`id`)、
 キー `idx_status` (`status`)
)ENGINE=InnoDB デフォルト文字セット=utf8;

# 1000w データを挿入するストアド プロシージャを作成する CREATE PROCEDURE insert_1000w()
始める
  i INT を宣言します。
  i=1 を設定します。
  i<=10000000の場合
    t6(name,status) に VALUES('god-jiang-666',1) を挿入します。
    i=i+1 を設定します。
  終了しながら;
終わり;

#ストアド プロシージャを呼び出して 1,000 万行のデータを挿入します。call insert_1000w();

2. 実験結果を分析する

# 0.572秒かかりました select count(*) from t6; 

ここに画像の説明を挿入

# 0.572秒かかりました select count(1) from t6; 

ここに画像の説明を挿入

# 0.580秒かかりました select count(id) from t6; 

ここに画像の説明を挿入

# 0.620秒かかりました select count(*) from t6 force index (primary); 

ここに画像の説明を挿入

上記の実験から、 count(*) と count(1) が最も速く、次に count(id) が続き、count が必須の主キーを使用する場合に最も遅いことがわかります。

それぞれの実行プランをテストし続けましょう。

select count(*) from t6; を説明します。
警告を表示します。 

ここに画像の説明を挿入

ここに画像の説明を挿入

t6からcount(1)を選択することを説明する。
警告を表示します。 

ここに画像の説明を挿入

ここに画像の説明を挿入

t6からcount(id)を選択する方法を説明します。
警告を表示します。 

ここに画像の説明を挿入

ここに画像の説明を挿入

select count(*) from t6 force index (primary); を説明します。
警告を表示します。 

ここに画像の説明を挿入

ここに画像の説明を挿入

上記の実験から、次の 3 つの点がわかります。

  1. MySQL クエリ オプティマイザーは count(*) を count(0) に書き換え、idx_status インデックスを選択します。
  2. count(1)とcount(id)はどちらもidx_statuxインデックスを選択します。
  3. フォースインデックス(プライマリ)を追加した後、強制インデックスが使用されます。

この idx_status は、セカンダリ補助インデックス ツリーに相当します。その目的は、InnoDB が count(*) を処理するときに、補助インデックス ツリーがある場合は、補助インデックス ツリーを優先して行の総数をカウントすることを示すことです。

count(*) が補助インデックス ツリーを優先するという結論を確認するために、次の実験を続けましょう。

# idx_statusインデックスを削除し、count(*)の実行を続行します。
テーブル t6 を変更してインデックス idx_status を削除します。

select count(*) from t6; を説明します。 

ここに画像の説明を挿入

上記の実験から、補助インデックス ツリー idx_status が削除された場合、count(*) は主キー インデックスの使用を選択することがわかります。結論としては、 count(*) は補助インデックスを優先します。補助インデックスがない場合は、主キー インデックスが使用されます。

count(*) がセカンダリインデックスを優先するのはなぜですか?

MySQL 5.7.18 より前では、InnoDB はクラスター化インデックスをスキャンして count(*) ステートメントを処理していました。

MySQL 5.7.18 以降、InnoDB は利用可能な最小のセカンダリ インデックスをトラバースして COUNT(*) ステートメントを処理します。セカンダリ インデックスが存在しない場合は、クラスター化インデックスがスキャンされます。

新しいバージョンでは、count(*) の処理にセカンダリ インデックスが使用されるのはなぜですか?

InnoDB セカンダリ インデックス ツリーのリーフ ノードには主キーが格納され、主キー インデックス ツリーのリーフ ノードにはデータの行全体が格納されるため、セカンダリ インデックス ツリーは主キー インデックス ツリーよりも小さくなります。したがって、クエリ オプティマイザーはコストを考慮してセカンダリ インデックスを優先します。したがって、インデックス count(*) は count(主キー) よりも高速です。

要約する

この記事の結論はcount(*)=count(1)>count(id)です。

主キーインデックスがないと count(id) が遅くなるのはなぜですか? count(id) は主キーを取得し、それが空かどうかを確認してから累積する必要があるため、コストが高くなります。

Count(*) はすべての NOT NULL および NULL フィールドをカウントしますが、count(id) は NULL フィールドをカウントしません。そのため、テーブルを構築するときは NOT NULL を使用し、デフォルトを空にするようにする必要があります。

最後に、将来的にデータベース テーブルの行数を合計したい場合は、count(*) または count(1) を大胆に使用できます。

参考文献

  • 「ハイパフォーマンス MySQL」(第 3 版)の第 6 章 COUNT() クエリの最適化
  • 「MySQL 実践 45 講義」Lin Xiaobin 著

MySQL COUNT(*)のパフォーマンスに関するこの記事はこれで終わりです。MySQL COUNT(*)の詳細については、123WORDPRESS.COMの以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも123WORDPRESS.COMをよろしくお願いいたします。

以下もご興味があるかもしれません:
  • 大規模な MySQL テーブルに対する count() の実装を最適化しました
  • MySQL の集計関数 count の使用法とパフォーマンスの最適化テクニック
  • MySQL の InnoDB におけるカウント最適化の問題の共有
  • MySQL の count 関数の正しい使い方の詳細な説明
  • MySQLの行数カウントに関する簡単な説明
  • MySQL カウントを向上させる方法のまとめ
  • MySQL でのフィルター条件なしのカウントの詳細な説明
  • MySQL における count(*)、count(1)、count(col) の違いのまとめ
  • 複数のテーブルでの MySQL カウント データ例の詳細な説明
  • MySQL COUNT関数の使用と最適化

<<:  HTML テキスト ボックスの入力を数字と小数点のみに制限する

>>:  非ルートユーザーを使用してDockerコンテナでスクリプト操作を実行する

推薦する

vuex ベースのショッピングカート機能の実装

この記事の例では、ショッピングカート機能を実装するためのvuexの具体的なコードを参考までに共有して...

Docker に nginx をインストールし、https 経由でアクセスを構成する方法

1. 最新のnginx dockerイメージをダウンロードする $ docker pull ngin...

JavaScript プリミティブデータ型シンボルの詳細な説明

目次導入説明名前の競合私有財産要約する導入シンボル変数を作成する最も簡単な方法は、Symbol() ...

Linuxでテキスト比較を実現するコツを教えます

序文コードを書く過程で、必然的にコードに何らかの変更を加えることになります。しかし、変更を加えるとき...

MySQLの最適化の詳細な分析とパフォーマンス

導入データベースを使用したことがある人なら、機能面での like 記号と = 記号の類似点と相違点を...

js でオブジェクトとオブジェクト メソッドを作成するいくつかの方法の詳細な説明

この記事は、JS レッドブックの第 8 章に記載されているオブジェクトに関する 2 番目の記事です。...

Vue でコミュニケーションを実装する 8 つの方法

目次1. コンポーネント通信1. Props 親コンポーネント ---> 子コンポーネント通信...

Linux での NVIDIA GPU 使用状況の監視の詳細な説明

TensorFlow をディープラーニングに使うとビデオメモリ不足がよく起こるので、GPU 使用状況...

HTML_PowerNode 入門 Java アカデミー

HTMLとは何ですか? HTML は Web ページを記述するために使用される言語です。 HTML ...

WeChatアプレットがシンプルな計算機機能を実装

この記事では、WeChatアプレットの計算機機能を実装するための具体的なコードを参考までに紹介します...

Linux ベースの MySQL マスター スレーブ構成の全プロセスを記録する

mysql マスタースレーブ構成1. 準備ホスト: 192.168.244.128スレーブ: 192...

Tomcat10 Catalinaのログの文字化けの問題を解決する

実行環境、Idea2020バージョン、Tomcat10、実行時にTomcat CatalinaLog...

mysql 5.7.11 winx64.zip インストールと設定方法のグラフィックチュートリアル

MySql データベース システムをインストールして構成します。 1. ダウンロード http://...

ホバードロップダウンメニューを実装するためのネイティブJS

JS はホバー ドロップダウン メニューを実装します。これは、フロントエンドの面接で遭遇するシナリ...

オンラインMySQLオプティマイザの誤判断によって発生した低速クエリイベントを記録する

序文:非常に遅いクエリとリクエストのタイムアウトのアラートを受け取りました。メトリックを通じて My...