MySQL COUNTステートメントは、インタビュアーにとって非常に惨めなものになる可能性があります。?

MySQL COUNTステートメントは、インタビュアーにとって非常に惨めなものになる可能性があります。

トピックに含まれる

15アリ開発マニュアルの解釈
△コーディングを独自に追求する
MySQL COUNTステートメントは、インタビュアーにとって非常に惨めなものになる可能性があります。 ?
ホリスこれはホリスの232回目のオリジナルシェアリングです

著者
lHollisソースlHollis(ID:hollischuang)
データベースクエリは多くの人に馴染みがあると考えられています。しばしば嘲笑されるプログラマーはすべてCRUDスペシャリストです。いわゆるCRUDはデータベースの追加、削除、変更を指します。

データベースの追加、削除、変更、およびクエリ操作では、クエリ操作が最も頻繁に使用されます。すべてのクエリ操作で、統計量操作がよく使用されます。

データベースの行数に関しては、MySQLであろうとOracleであろうと、使用できる関数、つまりCOUNTがあります。

しかし、多くの謎を隠すのはこの一般的に使用されるCOUNT関数であり、特にインタビュー中に、注意しないと虐待されます。信じられない場合は、次の質問に答えてみてください。

1、COUNT有几种用法?
2、COUNT(字段名)和COUNT(*)的查询结果有什么不同?
3、COUNT(1)和COUNT(*)之间有什么不同?
4、COUNT(1)和COUNT(*)之间的效率哪个更高?
5、为什么《阿里巴巴Java开发手册》建议使用COUNT(*)
6、MySQL的MyISAM引擎对COUNT(*)做了哪些优化?
7、MySQL的InnoDB引擎对COUNT(*)做了哪些优化?
8、上面提到的MySQL对COUNT(*)做的优化,有一个关键的前提是什么?
9、SELECT COUNT(*) 的时候,加不加where条件有差别吗?
10、COUNT(*)、COUNT(1)和COUNT(字段名)的执行过程是怎样的?

上記の10の質問すべてに正確に答えることができれば、それはCOUNT関数を本当に知っていることを意味します。理解できない知識ポイントがある場合は、この記事が質問に答えるのに役立ちます。

1.COUNTを知る

COUNT関数については、MySQLの公式Webサイトで詳しく説明されています。
MySQL COUNTステートメントは、インタビュアーにとって非常に惨めなものになる可能性があります。 ?

単に翻訳する:

1. COUNT(expr)は、EXPRの値がNULLではないというSELECTステートメントによって取得された行数を返します。結果はBIGINT値です。

2.クエリ結果がどのレコードにもヒットしない場合、0を返します。

3.ただし、COUNT(*)の統計結果には、値がNULLの行数が含まれることに注意してください。

つまり、次のテーブルレコード

create table #bla(id int,id2 int)
insert #bla values(null,null)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,null)

ステートメントcount(*)、count(id)、count(id2)を使用したクエリ結果は次のとおりです。

select count(*),count(id),count(id2)
from #bla
results 7 3 2

COUNT(id)とCOUNT()に加えて、COUNT(constant)(COUNT(1)など)を使用して行数をカウントすることもできます。これら3つのSQLステートメントの違いは何ですか。どちらがより効率的ですか?「AlibabaJava開発マニュアル」で、COUNT()の代わりにCOUNT(列名)またはCOUNT(定数)を使用しないことが必須なのはなぜですか?
MySQL COUNTステートメントは、インタビュアーにとって非常に惨めなものになる可能性があります。 ?

COUNT(列名)、COUNT(定数)、COUNT(*)の違い

先ほど、COUNT(expr)を使用して行数をカウントすることを説明しました。カウントは、exprがNULLでない行数です。次に、COUNT(列名)、COUNT(定数)、およびCOUNT()、expr3つの構文でそれぞれ列名、定数、およびです。

次に、列名、定数、およびこれら3つの条件、定数は固定値であり、確かにNULLではありません。行全体をクエリすることと理解できるため、NULLであってはなりません。したがって、列名のみのクエリ結果はNULLになる可能性があります。

したがって、COUNT(定数)およびCOUNT(*)は、基準を満たすデータベーステーブルの行数を示します。COUNT(列名)は、クエリを満たす列の値がNULLでない行の数を示します。

クエリによって取得された結果セットの違いに加えて、COUNT()はCOUNT(定数)およびCOUNT(列名)と比較されます。COUNT()は、SQL92で定義された標準のカウント行の構文です。これは標準の構文であるため、MySQLデータベースは彼のために多くの最適化を実行しました。

SQL92,是数据库的一个ANSI/ISO标准。它定义了一种语言(SQL)以及数据库的行为(事务、隔离级别等)。

COUNT(*)の最適化

前述のように、COUNT(*)はSQL92で定義された行数をカウントするための標準構文であるため、MySQLデータベースは彼のために多くの最適化を行いました。それで、あなたは正確に何をしましたか?

ここでの紹介では、さまざまな実行エンジンを区別します。MySQLでより一般的に使用される実行エンジンは、InnoDBとMyISAMです。

MyISAMとInnoDBには多くの違いがあります。主な違いの1つは、次に紹介するCOUNT(*)に関連しています。つまり、MyISAMはトランザクションをサポートしていません。MyISAMのロックはテーブルレベルのロックです。InnoDBはトランザクションをサポートし、行をサポートします。レベルロック。

MyISAMロックはテーブルレベルのロックであるため、同じテーブルに対する操作を連続して実行する必要があります。したがって、MyISAMは単純な最適化を行いました。つまり、テーブルからCOUNTを使用すると、テーブルの合計行数を個別に記録できます。 (*)クエリを実行するときは、もちろん、where条件がない限り、記録された値を直接返すことができます。

MyISAMがCOUNT(*)クエリのテーブルの合計行数を記録できる理由は、MyISAMデータベースがテーブルレベルのロックであり、データベースの行番号が同時に変更されないため、クエリによって取得される行数が正確であるためです。

ただし、InnoDBの場合、この種のキャッシュ操作は実行できません。これは、InnoDBがトランザクションをサポートし、そのほとんどが行レベルのロックであるため、テーブル内の行数が同時に変更される可能性があるため、キャッシュに記録される行の総数です。正確ではありません。

ただし、InnoDBは引き続きCOUNT(*)ステートメント用に最適化されています。

InnoDBでは、COUNT(*)を使用して行数を照会する場合、テーブルをスキャンすることは避けられません。そうすれば、テーブルをスキャンするプロセスの効率を最適化するために一生懸命働くことができます。

MySQL 8.0.13以降、InnoDBのSELECT COUNT(*)FROM tbl_nameステートメントに対して、テーブルのスキャンプロセスで実際にいくつかの最適化が行われました。クエリステートメントにWHEREやGROUPBYなどの条件が含まれていないことが前提です。

COUNT(*)の目的は行の総数をカウントすることだけであることがわかっているため、彼は見つけた特定の値を気にしません。したがって、テーブルスキャンプロセス中に低コストのインデックスを選択できる場合は、それは時間を節約することができます。

ご存知のとおり、InnoDBのインデックスは、クラスター化インデックス(プライマリキーインデックス)と非クラスター化インデックス(非プライマリーキーインデックス)に分けられます。クラスター化インデックスのリーフノードは、クラスター化インデックスのリーフノードではなく、レコードの行全体を格納します。行に記録されている主キーの値です。

したがって、対照的に、非クラスター化インデックスはクラスター化インデックスよりもはるかに小さいため、MySQLは、テーブルをスキャンするために最小の非クラスター化インデックスを優先します。したがって、テーブルを作成するときは、プライマリキーインデックスに加えて、非プライマリキーインデックスを作成する必要があります。

これまで、MySQLデータベースにCOUNT(*)の最適化を導入しました。これらの最適化の前提は、クエリステートメントにWHERE条件とGROUPBY条件が含まれていないことです。

COUNT(*)和COUNT(1)

COUNT(*)を紹介した後、COUNT(1)を見てみましょう。両者に違いがあるかどうかについては意見が異なります。

COUNT(*)は実行時にCOUNT(1)に変換されるため、COUNT(1)の変換ステップが少なくなり、高速になるという意見もあります。

また、MySQLCOUNT(に対して特別な最適化行っているため、COUNT()の方が高速であるとも言われています

それで、どのステートメントが正しいですか?MySQLの公式ドキュメントの内容をご覧ください。


InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.

塗装の焦点:同じように、パフォーマンスの違いはありません。したがって、COUNT(1)とCOUNT(*)の場合、MySQLの最適化はまったく同じであり、誰よりも速い人は誰もいません。

COUNT(*)はCOUNT(1)と同じなので、どちらをお勧めしますか?

COUNT(*)の使用をお勧めします!これはSQL92で定義された行数をカウントするための標準的な文法であり、この記事はMySQLの分析のみに基づいているため、Oracleではこの問題についてさまざまな意見があります。

COUNT(フィールド)

最後に、言及しなかったのはCOUNT(フィールド)です。彼のクエリは比較的単純で失礼です。テーブル全体をスキャンしてから、指定したフィールドの値がNULLかどうかを判断し、NULLでない場合は累積されます。

COUNT(と比較すると、COUNT(field)にはクエリフィールドがNULLかどうかを判断するためのステップがもう1つあるため、そのパフォーマンスはCOUNT(よりも遅くなります

総括する

この記事では、主にテーブルの行数をカウントするために使用されるCOUNT関数の使用法を紹介します。主な用途は、COUNT(*)、COUNT(フィールド)、およびCOUNT(1)です。

COUNT()はSQL92で定義された行数をカウントするための標準構文であるため、MySQLはそれに多くの最適化を行いました。MyISAMはCOUNT()クエリのテーブルの合計行数を直接記録し、 InnoDBはテーブルをスキャンします。コストを削減するために最小のインデックスを選択する時が来ました。もちろん、これらの最適化の前提は、場所とグループの条件付きクエリがないことです。

InnoDBでは、COUNT(*)とCOUNT(1)の実装に違いはなく、効率は同じですが、COUNT(フィールド)ではフィールドをNULL以外で判断する必要があるため、効率が低下します。

COUNT()はSQL92で定義された行をカウントするための標準構文であり、効率的であるため、COUNT()を直接使用してテーブルの行数照会してください。

参考資料:
https //dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_count
「オタク時間-MySQLの実際の戦闘に関する45の講義」
MySQL COUNTステートメントは、インタビュアーにとって非常に惨めなものになる可能性があります。 ?

Java Wayパブリックアカウントに注目し、オリジナルのJava技術記事を定期的に公開することを歓迎します〜

  • もっと|もっとエキサイティングな記事-

  • 私のガールフレンドは真夜中に長い間家に帰らなかった、そして彼女の携帯電話をタップした後の結果は私を壊した
  • ByteDanceのCEOであるZhangYimingは、HRを爆破しました。「この要件によると、私は自分で入ることはできません!」
  • Googleのソフトウェアエンジニアリング文化:創造性を刺激し、自律性を促進する
  • 2019年9月の全国プログラマー給与統計、どこにいますか?

この記事が気に入ったら
QRコードを長押し
MySQL COUNTステートメントは、インタビュアーにとって非常に惨めなものになる可能性があります。 ?
してホリスをフォローしください。友達の輪に転送してください。これが私の最大のサポートです。
良い記事、私は❤️を読んでいます

おすすめ

転載: blog.51cto.com/13626762/2544316