カウント(*) 成し遂げる 1. MyISAM: テーブル内の行の総数をディスク上に保存し、フィルタリング条件なしでクエリの行数を直接返すことができます。 count(*) フィルター条件がある場合、MyISAM はすぐに返されません。 2. InnoDB: ストレージエンジンからデータを行ごとに読み取り、カウントを累積する MVCC のため、InnoDB が同時に返す行数は不確実です。 例 テーブルtに10,000件のレコードがあると仮定する
最後の瞬間、3つのセッションが同時にtの行の合計数を照会しますが、結果は異なります。 InnoDBのデフォルトのトランザクション分離レベルはRRであり、MVCCを通じて実装されています。
最適化 1. InnoDBはインデックス構成テーブルです
2. セカンダリインデックスツリーが占めるスペースは、クラスター化インデックスツリーのスペースよりもはるかに小さい 3. オプティマイザーは最小のインデックス ツリーをトラバースし、正しいロジックを確保しながらスキャンされるデータの量を最小限に抑えます。
テーブルステータスを表示 mysql> テーブルステータスを表示\G; ************************** 1. 行 **************************** 名前: t エンジン: InnoDB バージョン: 10 行形式: 動的 行数: 100256 平均行長: 47 データ長: 4734976 最大データ長: 0 インデックスの長さ: 5275648 データ空き容量: 0 自動増分: NULL 作成時間: 2019-02-01 17:49:07 更新時間: NULL チェック時間: NULL 照合順序: utf8_general_ci チェックサム: NULL 作成オプション: コメント: SHOW TABLE STATUSもサンプリング(非常に不正確)を通じて推定し、誤差は40%~50%です。 メンテナンス回数 キャッシュ プラン
欠点 更新情報が失われました 1. Redisは更新を失う可能性がある 2. 解決方法: Redisが異常再起動したら、データベースでcount(*)を1回実行します。
不正確な論理 – 致命的 1. シナリオ: 操作記録の総数と最新の操作記録100件を表示する 2. Redis と MySQL は 2 つの異なるストレージ システムであり、分散トランザクションをサポートしていないため、正確で一貫したビューを取得することは不可能です。 タイミングA T3 の時点で、セッション B は最後に挿入されたレコードを含む 100 行を見つけますが、Redis はまだ +1 を追加していないため、論理的な矛盾が生じます。
タイミングB T3 の時点で、セッション B は 100 行に最後に挿入されたレコードが含まれていないことを発見しますが、Redis は 1 行を追加しており、これは論理的な矛盾です。
データベース
カウントのパフォーマンス セマンティクス 1. count() は、返された結果セットを行ごとに判断する集計関数です。 count 関数のパラメータ値が NULL でない場合は累積値に 1 が加算され、それ以外の場合は加算されずに累積値が返されます。 2. カウント(フィールドF)
3. count(主キーID)、count(1)、count(*)
4. InnoDB エンジンは、サーバー層に必要なフィールドを返します。
パフォーマンス比較 カウント(フィールドF) 1. フィールド F が NULL を許可しないと定義されている場合、このフィールドをレコードから 1 行ずつ読み取り、判断に合格した後、1 行ずつ累積します。
2. フィールド F が NULL を許可するように定義されている場合、このフィールドをレコードから 1 行ずつ読み取り、判定を通過した後、1 行ずつ累積します。
3. フィールドFにセカンダリインデックスがない場合、テーブル全体をトラバースすることしかできません(クラスター化インデックス) 4. InnoDBはフィールドFを返す必要があるため、オプティマイザは最適化の決定を少なくすることができます。
count(主キーID)
カウント(1)
カウント(*)
効率ランキング
例 mysql> SHOW CREATE TABLE prop_action_batch_reward\G; ************************** 1. 行 **************************** テーブル: prop_action_batch_reward テーブルの作成: CREATE TABLE `prop_action_batch_reward` ( `id` bigint(20) NULLではない、 `source` int(11) デフォルト NULL, `serial_id` bigint(20) NOT NULL, `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP、 `user_ids` 中テキスト、 `serial_index` tinyint(4) デフォルト '0', 主キー (`id`)、 ユニークキー `uniq_serial_id_source_index` (`serial_id`,`source`,`serial_index`), キー `idx_create_time` (`create_time`) ) エンジン=InnoDB デフォルト文字セット=utf8 カウント(フィールドF) インデックスなし user_ids にはインデックスがありませんが、InnoDB は user_ids フィールドを返す必要があるため、クラスター化インデックスのみをトラバースできます。 mysql> EXPLAIN SELECT COUNT(user_ids) FROM prop_action_batch_reward; +----+-------------+--------------------------+------+---------------+-------+------+------+------+------+ | id | select_type | テーブル | タイプ | possible_keys | key | key_len | ref | 行 | 追加 | +----+-------------+--------------------------+------+---------------+-------+------+------+------+------+ | 1 | シンプル | prop_action_batch_reward | すべて | NULL | NULL | NULL | NULL | 16435876 | NULL | +----+-------------+--------------------------+------+---------------+-------+------+------+------+------+ mysql> prop_action_batch_reward から COUNT(user_ids) を選択します。 +-----------------+ | ユーザーIDをカウント | +-----------------+ |17689788 | +-----------------+ セット1列目(10.93秒) インデックス付き 1. serial_idにはインデックスがあり、uniq_serial_id_source_indexでトラバースできます。 2. ただし、InnoDB は serial_id フィールドを返す必要があるため、論理的に同等の idx_create_time を走査しません。
mysql> EXPLAIN SELECT COUNT(serial_id) FROM prop_action_batch_reward; +----+-------------+---------------------------+--------+---------------+-----------------------------+--------+-----------+-------------+ | id | select_type | テーブル | タイプ | possible_keys | key | key_len | ref | 行 | 追加 | +----+-------------+---------------------------+--------+---------------+-----------------------------+--------+-----------+-------------+ | 1 | SIMPLE | prop_action_batch_reward | インデックス | NULL | uniq_serial_id_source_index | 15 | NULL | 16434890 | インデックスを使用 | +----+-------------+---------------------------+--------+---------------+-----------------------------+--------+-----------+-------------+ mysql> prop_action_batch_reward から COUNT(serial_id) を選択します。 +------------------+ | カウント(シリアルID) | +------------------+ |17705069 | +------------------+ セット1列目(5.04秒) count(主キーID) オプティマイザは、クラスタ化インデックスの代わりに、トラバースする最適なインデックスidx_create_timeを選択します。 mysql> EXPLAIN SELECT COUNT(id) FROM prop_action_batch_reward; +----+-------------+---------------------------+--------+---------------+---------+-----------+-------------+ | id | select_type | テーブル | タイプ | possible_keys | key | key_len | ref | 行 | 追加 | +----+-------------+---------------------------+--------+---------------+---------+-----------+-------------+ | 1 | SIMPLE | prop_action_batch_reward | インデックス | NULL | idx_create_time | 5 | NULL | 16436797 | インデックスを使用 | +----+-------------+---------------------------+--------+---------------+---------+-----------+-------------+ mysql> prop_action_batch_reward から COUNT(id) を選択します。 +-----------+ | カウント(ID) | +-----------+ |17705383 | +-----------+ セット1列目(4.54秒) カウント(1) mysql> EXPLAIN SELECT COUNT(1) FROM prop_action_batch_reward; +----+-------------+---------------------------+--------+---------------+---------+-----------+-------------+ | id | select_type | テーブル | タイプ | possible_keys | key | key_len | ref | 行 | 追加 | +----+-------------+---------------------------+--------+---------------+---------+-----------+-------------+ | 1 | SIMPLE | prop_action_batch_reward | インデックス | NULL | idx_create_time | 5 | NULL | 16437220 | インデックスを使用 | +----+-------------+---------------------------+--------+---------------+---------+-----------+-------------+ mysql> prop_action_batch_rewardからCOUNT(1)を選択します。 +----------+ | カウント(1) | +----------+ |17705808 | +----------+ セット1列目(4.12秒) カウント(*) mysql> EXPLAIN SELECT COUNT(*) FROM prop_action_batch_reward; +----+-------------+---------------------------+--------+---------------+---------+-----------+-------------+ | id | select_type | テーブル | タイプ | possible_keys | key | key_len | ref | 行 | 追加 | +----+-------------+---------------------------+--------+---------------+---------+-----------+-------------+ | 1 | SIMPLE | prop_action_batch_reward | インデックス | NULL | idx_create_time | 5 | NULL | 16437518 | インデックスを使用 | +----+-------------+---------------------------+--------+---------------+---------+-----------+-------------+ mysql> prop_action_batch_reward から COUNT(*) を選択します。 +----------+ | カウント(*) | +----------+ |17706074| +----------+ セット1列目(4.06秒) 参考文献 「MySQL実践45講義」 要約する 上記はこの記事の全内容です。この記事の内容が皆さんの勉強や仕事に一定の参考学習価値を持つことを願っています。ご質問があれば、メッセージを残してコミュニケーションしてください。123WORDPRESS.COM を応援していただきありがとうございます。 以下もご興味があるかもしれません:
|
<<: VantフレームワークをWeChatアプレットに導入するプロセス全体の記録
>>: Linux が Sudo 権限昇格の脆弱性を公開、どのユーザーでも root コマンドを実行可能
マウスの位置をマッピングしたり、ドラッグ効果を実装したりすることは、 JavaScriptで行うこと...
Black Duck の 2017 年のオープンソース調査では、回答者の 77% がオープンソース...
W3C は最近、「 XHTML Basic1.1 」と「 Mobile Web Best Prac...
1. ネイティブネットワークリクエスト1. XMLHttpRequest (W3C 標準) // 約...
目次1. beforeCreate & created 2. マウント前とマウント済み3. ...
序文インターセプター最近のフロントエンド フレームワークでは、インターセプターは基本的に非常に基本的...
webpack-dev-server コアコンセプトWebpack の ContentBase と ...
目次1. サーバーの状態を確認します。 2. ルートパスワードを変更します。 3. mysqlser...
ウェブサイトのレイアウトの多様化は、当社のフロントエンドの得意分野です。最近、UC ブラウザのデフォ...
この記事では、ネイティブ JS で実装されたドラッグ可能なログイン ボックスを紹介します。その効果は...
この記事の例では、WeChatアプレットで画像コントロールを選択するための具体的なコードを参考までに...
目次序文基本的な使い方文法エラー処理プロミスチェーン呼び出し非同期と待機よく使われる方法1. Pro...
目次初期作成方法ファクトリーパターンコンストラクターパターンコンストラクタパターンの最適化プロトタイ...
ssh は私が最も頻繁に使用する 2 つのコマンドライン ツールのうちの 1 つです (もう 1 つ...
<base target=_blank> は、基本リンクのターゲット フレームを新しいペ...