Mysql Explain でフィルターされた列の値が常に 100% 拡張されるのはなぜですか_PHP チュートリアル
Mysql Explain Extended のフィルターされた列の値が常に 100% になる理由
1. 問題
Mysql Explain Extended を実行した出力には、単純な Explain よりも 1 つ多くのフィルターされた列が含まれます (MySQL5.7 はデフォルトでフィルターされた出力になります)。読み取る必要がある行のうち、結果を返す行の割合 (行列の値) を指します。結合操作の場合、前のテーブルの結果セットのサイズがループの数に直接影響するため、filtered は非常に便利な値であると言われています。しかし、私の環境でテストした結果、filtered の値は常に 100% となり、意味が失われています。以下の MySQL 5.6 コードを参照してください。フィルターされた値は、インデックスとすべてのスキャンに対してのみ有効です (これは理解できます。他の状況では、行の値は通常、推定された結果セット サイズと等しくなります)。
sql/opt_explain.cc
- bool Explain_join::explain_rows_and_filtered()
- {
- if (table->pos_in_table_list->schema_table)
- return false;
-
- 二重検査行;
- if (選択 && 選択->クイック)
- examined_rows= rows2double(選択->クイック->レコード);
- else if (タブ->タイプ == JT_INDEX_SCAN || タブ->タイプ == JT_ALL)
- {
- if (タブ->制限)
- examined_rows= rows2double(タブ->制限);
- else
- {
- table->pos_in_table_list->fetch_number_of_rows ();
- selected_rows= rows2double(table->file->stats.records);
- }
- }
- else
- examined_rows= tab->position->records_read;
- fmt- >エントリー()->col_rows.set(static_cast
(examined_rows)); - /* 「フィルターされた」フィールドを追加 */
- if (describe(DESCRIBE_EXTENDED))
- {
- float f= 0.0;
- if (examined_rows)
- f= 100.0 * tab->position->records_read / inspired_rows;
- fmt->entry()->col_filtered.set(f);
- }
- return false;
- }
しかし、フルテーブルスキャンを構築した後、フィルタリングされた結果は依然として 100% であり、期待していた値は 0.1% でした。
- mysql> desc tb2;
+-------+--------------+------+-----+---- --+------+
| デフォルト |
+------+---------- --+------+-----+------+-----+
| 0 | |
| int(11) |
| varchar(100) | ----+------+-----+-----------+----------+
セット内の 3 行 (0.00 秒)
mysql> Explain拡張選択 * from tb2 where c1+----+-------------+-------+------+---- -----------+------+--------+------+--------+----- -----+----------+ | 選択可能なキーの行 |
+-------------+----------+------+--------+---- --+----------+------+----------+----------+---------- ---+
| tb2 | 996355 | を使用します。 -------+------+------+------+-----------+-- --------+----------+----------+---------------+
セット内 1 行、警告 1 つ (10 分) 29.96 秒)
mysql> select count(*) from tb2 where c1+----------+
count(*) |+---------- -+
| 1001 |
+----------+
セット内の 1 行 (1.99 秒)
(gdb)p table-> file->statords
- $ 18 =996355
- なぜ上記のような状況が起こるのでしょうか?その後、MySQLが収集する統計情報を確認して理解しました。 MySQL は、他の主流データベースと同様に、より適切な実行計画を生成するために統計情報を自動的に収集する必要があります。収集された統計情報は、mysql.innodb_table_stats および mysql.innodb_index_stats に保存されます。
しかし、重要なのは、これらを確認することです。 2 表から、MySQL が収集する統計情報はほとんどないことがわかります。
mysql> select * from mysql.innodb_table_stats where table_name='tb2';
+---------------+------------+- --------------------+--------+---------------------- --+--------------------------+
|データベース名 |テーブル名 |最後の更新 | n_行 |クラスター化インデックスのサイズ | sum_of_other_index_sizes |
+---------------+------------+----------------- ----+--------+-----------+--------------- -------------+
|テスト | TB2 | 2015-12-02 06:26:54 | 996355 | 3877 | 0 |
+---------------+-----------+----------------- ----+--------+-----------+--------------- -------------+
セット内の 1 行 (0.00 秒)
mysql> select * from mysql.innodb_index_stats where table_name='tb2';
+-------- -------+-----------+---------------+----- ----------+--------------+-----------+---------------+-- ---------------------------------+
|データベース名 |テーブル名 |インデックス名 |最後の更新 |統計名 |統計値 |サンプルサイズ | stat_description |
+------+------------+------------+---- ----------+--------------+-----------+------ --------+-----------------------------------+
|テスト | TB2 |プライマリ | 2015-12-02 06:26:54 | n_diff_pfx01 | 996355 | 20 | ID |
|テスト | TB2 |プライマリ | 2015-12-02 06:26:54 | n_leaf_pages | 3841 | NULL |インデックス内のリーフ ページの数 |
|テスト | TB2 |プライマリ | 2015-12-02 06:26:54 |サイズ | 3877 | NULL |インデックス内のページ数 |
+--------------+---------------+------------ +---------------------+--------------+--------------- +-------------+------------------------------------- +
セット内の 3 行 (0.00 秒)
重要な情報は 2 つあり、1 つはテーブルの総承認数 (n_rows)、2 つはインデックス内の列の唯一の数 (n_diff_pfx01) です。 MySQL はインデックス以外の値情報を処理できません。前述の例では、c1 にインデックスが付けられていないため、MySQL は「c1
3. 引申請
後面私は MySQL 不足の统计情報会議に関係しています、何後の結果ですか?- mysql> tb1,tb2 からの拡張選択カウント (*) について説明します。ここで、tb1.c1=tb2.c1 および tb2.c2='xx';
- +----+------ -------+------+------+---------------------+------+---- ----------+------+----------+----------+------ -----------------------------------+
| ID |選択タイプ |テーブル |タイプ |可能なキー |キー |キー長 |参照 |行 |フィルタリング済み |おまけ |
+------+---------------+-------+------+------------ ---+------+--------+------+----------+----------+-- -------------------------------------------------- +
| 1 |シンプル | tb1 |すべて | NULL | NULL | NULL | NULL | 1000 | 100.00 | NULL |
| 1 |シンプル | TB2 |すべて | NULL | NULL | NULL | NULL | 996355 | 100.00 | where を使用する;結合バッファーの使用 (ブロックネストループ) |
+----+-------------+----------+------+----- ----------+------+----------+------+----------+------ ----+------------------------------------------ -------+
セット内 2 行、警告 1 件 (0.00 秒)
postgres=# Explain select count(*) from tb1,tb2 where tb1.c1=tb2.c1 and tb2.c2='xx';
- クエリプラン
- -------- -------------------------------------------------- --------
- 集計 (コスト=20865.50..20865.51 行=1 幅=0)
- -> ネストされたループ (コスト=0.00..20865.50 行=1 幅=0)
- 結合フィルター: (tb1.c1 = tb2.c1)
- -> tb2 のシーケンススキャン (コスト=0.00..20834.00 行=1 幅=4)
- フィルター: ((c2)::text = 'xx '::text)
- -> tb1 での Seq Scan (コスト = 0.00..19.00 行 = 1000 幅 = 4)
- (6 行)
- 以下の実行時間を見る。
mysql> select count(*) from tb1,tb2 where tb1.c1=tb2.c1 and tb2.c2='xx';
- +---------- +
- |カウント(*) |
- +----------+
- | 0 |
- +----------+
- セット内の1行(0.34秒)
- PostgreSQL花了0.139s
- postgres=# select count(*) from tb1,tb2 where tb1.c1=tb2.c1 and tb2.c2='xx';
- count
- -----
- 0
- (1 row)
- Time: 139.600 ms
上記の例のパフォーマンスの差は、実際には tb2.c2='xx' の条件を取り除くとそれほど大きくありません。とても大きくなってください。
Mysql には 1 分 8 秒かかりました
- mysql> Explain select count(*) from tb1,tb2 where tb1.c1=tb2.c1;
+----+---------- - -+----------+-----+------+-----+--------- + ----------+----------+------------------------------------- ------------------+
| テーブルのタイプ | キー長 |
-----------+------+------+---------------------+------ + --------+------+----------+---------------------- - -----------------------------+
| 1 | ヌル | | 1000 | 1 | 1 | 1 | 996355 | 結合バッファーを使用します。 -- ----+------+------+---------------------+------+----- -- --+------+----------+---------------------- ----- ---------------------+
セット内の 2 行 (0.00 秒)
mysql> select count(*) from tb1,tb2 ここでtb1.c1=tb2 .c1;
+----------+
| カウント(*) |
+----------+
| 9949 |
+--- ----- --+
セット内の 1 行 (1 分 8.26 秒)
postgres=# Explain select count(*) from tb1,tb2 where tb1.c1= tb2.c1;
-
クエリプラン -
------------------------------------- ------- ---------------------------------- -
集計 (コスト=23502.34. .23502.35 rows=1 width=0) -
-> ハッシュ結合 (cost=31.50..23474.97 rows=10947 width=0) -
Hash Cond: (tb2.c1 = tb1.c1) -
-> TB2 での Seq スキャン (コスト=0.00..18334.00 rows=1000000 width=4) -
-> ハッシュ (cost=19.00..19.00 rows=1000 width=4) -
-> tb1 での Seq Scan (cost= 0.00..19.00 rows=1000 width=4 ) -
(6 rows) -
Time: 0.690 ms -
postgres=# select count(*) from tb1,tb2 where tb1.c1=tb2。 c1; -
count -
- ------ -
10068 -
(1 row) -
Time: 163.868 ms
4. 概要
1. MySQL には統計情報がほとんどなく、テーブルの行数とインデックス列の一意の値の数しかないため、MySQL オプティマイザーはデータ サイズを正しく理解できないことがよくあります。実行計画のパフォーマンスが低下します。
2. MySQL の結合操作の効率はインデックスに大きく依存します (私が MySQL の SQL ステートメントのチューニングを手伝った過去 2 回はすべてインデックスでした)。 PG の結合にインデックスが必要ないわけではありませんが、MySQL にインデックスがないことほど大きな反響ではありません。上記の例では、MySQL の実行に 1 分以上かかりましたが、インデックスを追加した後、MySQL と PG の実行時間はすぐに 10 ミリ秒未満に短縮されました。したがって、開発者はテーブルを設計するときに可能なクエリ メソッドを評価し、構築する必要があるすべてのインデックスを (それ以下でもそれ以上でも) 構築する必要があります。
3. 対照的に、PG はすべての列の値の分布をカウントするだけでなく、一意の値に加えてヒストグラム、頻度の値、その他の情報も含めて、PG オプティマイザーが正しい決定を下せるようにサポートします。この理由から、PG コミュニティは、PG のオプティマイザは十分に賢く、Oracle のようなヒント機能を PG カーネルに追加する必要はないと考えていると推測されます (ヒントは人によって悪用される可能性があり、システムの保守が困難になるためです)。ただし、実際には、これを使用したい場合は、pg_hint_plan プラグインを自分でインストールできます)。http://www.bkjia.com/PHPjc/1080260.html
)
ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











ここ数日、Ice Universeは、サムスンの次期主力スマートフォンであると広く信じられているGalaxy S25 Ultraの詳細を着実に明らかにしている。とりわけ、リーカーはサムスンがカメラのアップグレードを1つだけ計画していると主張した

OnLeaks は、X (旧 Twitter) のフォロワーから 4,000 ドル以上を集めようとして失敗した数日後、Android Headlines と提携して Galaxy S25 Ultra のファーストルックを提供しました。コンテキストとして、h の下に埋め込まれたレンダリング イメージ

TCLは、2つの新しいスマートフォンの発表に加えて、NXTPAPER 14と呼ばれる新しいAndroidタブレットも発表しました。その巨大な画面サイズはセールスポイントの1つです。 NXTPAPER 14 は、TCL の代表的なブランドであるマット LCD パネルのバージョン 3.0 を搭載しています。

ここ数日、Ice Universeは、サムスンの次期主力スマートフォンであると広く信じられているGalaxy S25 Ultraの詳細を着実に明らかにしている。とりわけ、リーカーはサムスンがカメラのアップグレードを1つだけ計画していると主張した

Vivo Y300 Pro は完全に公開されたばかりで、大容量バッテリーを備えた最もスリムなミッドレンジ Android スマートフォンの 1 つです。正確に言うと、このスマートフォンの厚さはわずか 7.69 mm ですが、6,500 mAh のバッテリーを搭載しています。これは最近発売されたものと同じ容量です

Motorola は今年数え切れないほどのデバイスをリリースしましたが、そのうち折りたたみ式デバイスは 2 つだけです。ちなみに、世界の大部分ではこのペアが Razr 50 および Razr 50 Ultra として受け入れられていますが、Motorola は北米では Razr 2024 および Razr 2 として提供しています。

Redmi Note 14 Pro Plusは、昨年のRedmi Note 13 Pro Plus(Amazonで現在375ドル)の直接の後継者として正式に発表されました。予想通り、Redmi Note 14 Pro Plusは、Redmi Note 14およびRedmi Note 14 Proと並んでRedmi Note 14シリーズをリードします。李

サムスンは、ファンエディション(FE)スマートフォンシリーズをいつアップデートするかについて、まだ何のヒントも提供していない。現時点では、Galaxy S23 FE は 2023 年 10 月初めに発表された同社の最新版のままです。
