サブクエリ最適化における MySQL 選択の実装

サブクエリ最適化における MySQL 選択の実装

以下のデモはMySQLバージョン5.7.27に基づいています。

1. MySQLサブクエリ最適化戦略の概要:

サブクエリ最適化戦略

オプティマイザーは、サブクエリの種類に応じて異なる戦略を選択します。

1. IN および =ANY サブクエリの場合、オプティマイザには次の戦略の選択肢があります。

  • セミジョイン
  • 具体化
  • 存在する

2. NOT IN および <> ALL サブクエリの場合、オプティマイザには次の戦略の選択肢があります。

  • 具体化
  • 存在する

3. 派生テーブルの場合、オプティマイザには次の戦略オプションがあります。
derived_merge は、派生テーブルを外部クエリにマージします (5.7 で導入)。
派生テーブルを内部一時テーブルにマテリアライズし、それを外部クエリで使用します。
注意: 更新ステートメントおよび削除ステートメントのサブクエリでは、セミ結合またはマテリアライゼーション最適化戦略を使用できません。

2. シミュレーションデモンストレーション用のデータを作成する

問題の分析を容易にするために、2 つのテーブルを作成し、シミュレートされたデータを挿入します。

テーブル「test02」を作成します(
 `id` int(11) NULLではない、
 `a` int(11) デフォルト NULL,
 `b` int(11) デフォルト NULL,
 主キー (`id`)、
 キー `a` (`a`)
)ENGINE=InnoDB;

手順 idata を削除します。
デリミタ;;
プロシージャ idata() を作成する
始める
 iをintとして宣言します。
 i=1 に設定します。
 i<=10000の間、
  test02に値(i, i, i)を挿入します。
  i=i+1 と設定します。
 終了しながら;
終わり;;
区切り文字 ;
idata() を呼び出す。

test02 のようなテーブル test01 を作成します。
test01 に挿入 (test02 から id<=1000 の * を選択)

3. SQLインスタンスの分析例

サブクエリの例:

SELECT * FROM test01 WHERE test01.a IN (SELECT test02.b FROM test02 WHERE id < 10)

ほとんどの人は、この SQL が次のように実行されると考えるでしょう。

SELECT test02.b FROM test02 WHERE id < 10

結果: 1、2、3、4、5、6、7、8、9

test01 から * を選択 WHERE test01.a IN (1,2,3,4,5,6,7,8,9);

しかし、実際には MySQL はそうは動作しません。 MySQL は関連する外部テーブルをサブクエリにプッシュし、オプティマイザはこれがより効率的であると判断します。つまり、オプティマイザーは上記の SQL を次のように書き換えます。

存在する場合は test01 から * を選択します (ID < 10 かつ test01.a=test02.b の場合は test02 から b を選択します)。

ヒント: MySQL 5.5以前のバージョンの場合

次のように実行プランを確認すると、この SQL がテーブル test01 に対して完全なテーブル スキャンを 1000 回実行していることがわかります。これは非効率的です。

root@localhost [dbtest01]>desc select * from test01 where exists(select b from test02 where id < 10 and test01.a=test02.b);
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+
| 1 | PRIMARY | test01 | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 100.00 | where の使用 |
| 2 | 従属サブクエリ | test02 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 10.00 | where の使用 |
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+
セットに 2 行、警告 2 件 (0.00 秒)

しかし、実際に次の SQL を実行すると、まったく遅くないことがわかります。これは矛盾ではありませんか? 心配しないでください。分析を続けましょう。

SELECT * FROM test01 WHERE test01.a IN (SELECT test02.b FROM test02 WHERE id < 10)

この SQL の実行プランを次のように確認します。

root@localhost [dbtest01]>desc SELECT * FROM test01 WHERE test01.a IN (SELECT test02.b FROM test02 WHERE id < 10);
+----+--------------+--------------+------------+----------+---------------+---------+----------+------------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------+--------------+------------+----------+---------------+---------+----------+------------+-------------+
| 1 | SIMPLE | <subquery2> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | 100.00 | where の使用 |
| 1 | SIMPLE | test01 | NULL | ref | a | a | 5 | <サブクエリ2>.b | 1 | 100.00 | NULL |
| 2 | MATERIALIZED | test02 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 100.00 | where の使用 |
+----+--------------+--------------+------------+----------+---------------+---------+----------+------------+-------------+
セットに 3 行、警告 1 件 (0.00 秒)

オプティマイザーは MATERIALIZED 戦略を使用していることがわかります。そこで私は情報を検索し、この戦略を研究しました。
https://dev.mysql.com/doc/refman/5.6/en/サブクエリ最適化.html

その理由は、MySQL 5.6 以降、オプティマイザが新しい最適化戦略を導入したためです: マテリアライゼーション = [オフ|オン]、セミジョイン = [オフ|オン] (オフは、この戦略をオフにすることを意味し、オンは、この戦略をオンにすることを意味します)
MySQL で使用されるオプティマイザ戦略を表示するには、「show variables like 'optimizer_switch';」を使用できます。もちろん、これらの戦略はオンラインで動的に変更することもできます。
set global optimizer_switch='materialization=on,semijoin=on'; は、最適化戦略マテリアライゼーションとセミジョインをオンにすることを表します。

MySQL 5.7.27 のデフォルトのオプティマイザ戦略は次のとおりです。

root@localhost [dbtest01]> 'optimizer_switch' のような変数を表示します。                                                               
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 変数名 | 値 |
+------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| optimizer_switch | index_merge=on、index_merge_union=on、index_merge_sort_union=on、index_merge_intersection=on、engine_condition_pushdown=on、index_condition_pushdown=on、mrr=on、mrr_cost_based=on、block_nested_loop=on、batched_key_access=off、materialization=on、semijoin=on、loosescan=on、firstmatch=on、duplicateweedout=on、subquery_materialization_cost_based=on、use_index_extensions=on、condition_fanout_filter=on、derived_merge=on |
+------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

MySQL 5.6以降では

次の SQL を実行しても遅くなりません。 MySQLのオプティマイザ戦略マテリアライゼーションとセミジョインがこのSQLを最適化するため

SELECT * FROM test01 WHERE test01.a IN (SELECT test02.b FROM test02 WHERE id < 10)

ただし、テストのために MySQL オプティマイザー戦略のマテリアライゼーションとセミ結合をオフにしたところ、SQL が test01 (1000) のテーブル全体をスキャンしていることがわかりました。

グローバル optimizer_switch='materialization=off,semijoin=off' を設定します。

実行プランは次のようになります。test01 テーブルは実際に完全にスキャンされます。

root@localhost [dbtest01]>desc SELECT * FROM test01 WHERE test01.a IN (SELECT test02.b FROM test02 WHERE id < 10);
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+
| 1 | PRIMARY | test01 | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 100.00 | where の使用 |
| 2 | 従属サブクエリ | test02 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 10.00 | where の使用 |
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+
セットに 2 行、警告 1 件 (0.00 秒)

この実行計画を分析してみましょう。

! ! ! !再度のヒント: MySQL 5.5 以前のバージョン、または MySQL 5.6 以降のバージョンを使用し、オプティマイザ戦略の materialization=off、semijoin=off をオフにすると、取得する SQL 実行プランは次のようになります。

root@localhost [dbtest01]>desc select * from test01 where exists(select b from test02 where id < 10 and test01.a=test02.b);
+----+--------------------+---------+-----------+---------+---------------+----------+-------+----------+------------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------------+---------+-----------+---------+---------------+----------+-------+----------+------------+-------------+
| 1 | PRIMARY | test01 | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 100.00 | where の使用 |
| 2 | 従属サブクエリ | test02 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 10.00 | where の使用 |
+----+--------------------+---------+-----------+---------+---------------+----------+-------+----------+------------+-------------+
セットに 2 行、警告 2 件 (0.00 秒)

非相関サブクエリは相関サブクエリ (select_type:DEPENDENT SUBQUERY) になります。サブクエリは、b に基づいて外部テーブル test01 に関連付ける必要があります。外部テーブルの test01 フィールドは必須であるため、サブクエリを最初に実行することはできません。実行プロセスは次のとおりです。

  1. test01 をスキャンし、test01 からデータ R の行を抽出します。
  2. データ行 R からフィールド a を取り出してサブクエリを実行します。結果が TRUE の場合、このデータ行 R を結果セットに格納します。
  3. 1と2を最後まで繰り返します。

スキャンされた行の合計数は 1000+1000*9=10000 です (これは理論値ですが、実際の値は 10000 未満です。この値がどのようにして得られたのかはわかりません。ルールとしては、サブクエリの結果セットに行が追加されるたびに、スキャンされた行の合計数が数行ずつ減少します)。

セミ結合オプティマイザー:

これにより問題が発生します。外部テーブルが非常に大きいテーブルの場合、サブクエリは外部クエリの各行に対して 1 回実行される必要があり、このクエリのパフォーマンスは非常に低下します。効率を上げるために、これを join に書き直すことは簡単に考えられます。

test01 から test01.* を選択し、test01.a=test02.b かつ test02.id<10 で test02 を結合します。

# この SQL の実行プランを表示します。

desc test01 から test01.* を選択し、test01.a=test02.b かつ test02.id<10 で test02 を結合します。

root@localhost [dbtest01]>EXPLAIN 拡張選択 test01.* から test01 を結合 test02 on test01.a=test02.b and test02.id<10;
+----+-------------+---------+-----------+----------+---------------+---------+----------+-------------------+------------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+---------+-----------+----------+---------------+---------+----------+-------------------+------------+-------------+
| 1 | SIMPLE | test02 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 100.00 | where の使用 |
| 1 | SIMPLE | test01 | NULL | ref | a | a | 5 | dbtest01.test02.b | 1 | 100.00 | NULL |
+----+-------------+---------+-----------+----------+---------------+---------+----------+-------------------+------------+-------------+
セットに 2 行、警告 2 件 (0.00 秒)

この最適化により、t2 テーブルが駆動テーブルとなり、t1 テーブルの関連フィールドにインデックスが付けられるため、検索効率が非常に高くなります。

しかし、ここで問題があります。結合では重複した結果が取得される可能性がありますが、(select ...) サブクエリのセマンティクスでは重複した値は取得されません。
セミ結合は重複値の問題を解決する特殊な結合です。
サブクエリでは、オプティマイザーは in 句内の各グループに対して 1 つの値のみを返す必要があることを認識できます。この場合、セミ結合を使用してサブクエリを最適化し、クエリの効率を向上させることができます。
これは、MySQL 5.6 で追加された新機能です。MySQL 5.6 より前では、オプティマイザにはサブクエリを「最適化」する戦略しかありませんでした。

セミ結合最適化後の SQL と実行プランは次のとおりです。

root@localhost [dbtest01]>desc SELECT * FROM test01 WHERE test01.a IN (SELECT test02.b FROM test02 WHERE id < 10);
+----+--------------+--------------+------------+----------+---------------+---------+----------+------------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------+--------------+------------+----------+---------------+---------+----------+------------+-------------+
| 1 | SIMPLE | <subquery2> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | 100.00 | where の使用 |
| 1 | SIMPLE | test01 | NULL | ref | a | a | 5 | <サブクエリ2>.b | 1 | 100.00 | NULL |
| 2 | MATERIALIZED | test02 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 100.00 | where の使用 |
+----+--------------+--------------+------------+----------+---------------+---------+----------+------------+-------------+
セットに 3 行、警告 1 件 (0.00 秒)
選択 
  `test01`.`id`、`test01`.`a`、`test01`.`b` 
`test01` から `test02` にセミ結合 
どこ
  ((`test01`.`a` = `<サブクエリ2>`.`b`) 
  そして (`test02`.`id` < 10)); 

##これはオプティマイザによって書き換えられた SQL であることに注意してください。セミ結合構文はクライアントでは使用できません。

セミ結合の最適化実装は比較的複雑で、FirstMatch や Materialize などの戦略に分かれています。上記の実行プランでは、select_type=MATERIALIZED は、セミ結合が Materialize 戦略を使用して実装されていることを意味します。
ここで、最適化後のセミ結合の実行フローは次のようになります。

まずサブクエリを実行し、結果を一時テーブルに保存します。この一時テーブルには重複排除用の主キーがあります。
一時テーブルからデータ R の行を取得します。
データ行Rからフィールドbを取り出し、駆動テーブルt1で検索します。条件を満たしている場合は、結果セットに入れます。
最後まで手順 2 と 3 を繰り返します。
このように、サブクエリの結果には 9 行があり、つまり、一時テーブルにも 9 行があり (ここでは重複する値はありません)、スキャンされた行の合計数は 9+9+9*1=27 行となり、元の 10,000 行よりはるかに少なくなります。

MySQL 5.6 で追加されたもう 1 つの最適化機能はマテリアライゼーションです。これは、サブクエリの結果を一時テーブルにマテリアライズし、それを検索用の外部クエリに代入して、クエリの実行を高速化します。メモリ内の一時テーブルには主キー (ハッシュ インデックス) が含まれ、重複行が削除され、テーブルが小さくなります。
サブクエリの結果が大きすぎて tmp_table_size を超える場合、ディスク一時テーブルに縮退します。この方法では、サブクエリは外部クエリの各行に対してではなく、1 回だけ実行する必要があります。
ただし、このような外部クエリでは、インデックスを通じて適切なデータを迅速に見つけることができず、完全なテーブル スキャンまたは完全なインデックス スキャンを通じてのみ実行できることに注意してください。

セミ結合とマテリアライゼーションの開始は、optimizer_switch パラメータの semijoin={on|off}、materialization={on|off} フラグによって制御されます。
上記の異なる実行プランは、セミジョインとマテリアライゼーションのオン/オフによって生成されます。一般的に、サブクエリの場合は、まずさまざまな最適化戦略の条件が満たされているかどうかを確認します(たとえば、サブクエリにユニオンがある場合は、セミジョイン最適化は使用できません)。
オプティマイザーはコストに基づいて選択を行います。他に選択肢がない場合は、exists 戦略を使用してサブクエリを「最適化」します。exists 戦略を有効または無効にするパラメーターはありません。

削除関連のサブクエリの例を次に示します。

上記の2つのテストテーブルにそれぞれ350万件のデータと50万件のデータを入力して、削除ステートメントをテストします。

root@localhost [dbtest01]>test02からcount(*)を選択します。
+----------+
| カウント(*) |
+----------+
|3532986|
+----------+
セット内1列(0.64秒)
root@localhost [dbtest01]>test02のようなテーブルtest01を作成します。
クエリは正常、影響を受けた行は 0 行 (0.01 秒)

root@localhost [dbtest01]>test01 に挿入 (test02 から * を選択、ID <= 500000)

root@localhost [dbtest01]>test01からcount(*)を選択します。
+----------+
| カウント(*) |
+----------+
| 500000 |

削除ステートメントの実行には 4 秒かかりました。

root@localhost [dbtest01]> test01 から test01.a を削除します (test02 から test02.b を選択します)。
クエリは正常、9 行が影響を受けました (4.86 秒)

実行プランを見ると、test01 テーブルがほぼ完全にスキャンされていることがわかります。

root@localhost [dbtest01]>desc delete FROM test01 WHERE test01.a IN (SELECT test02.b FROM test02 WHERE id < 10);
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+
| 1 | DELETE | test01 | NULL | ALL | NULL | NULL | NULL | NULL | 499343 | 100.00 | where の使用 |
| 2 | 従属サブクエリ | test02 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 10.00 | where の使用 |
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+
セット内の 2 行 (0.00 秒)

したがって、上記の削除SQL文を疑似結合文に変更します。

root@localhost [dbtest01]>desc test01 から test01.* を削除し、test01.a=test02.b および test02.id<10 で test02 を結合します。
+----+-------------+---------+-----------+----------+---------------+---------+----------+-------------------+------------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+---------+-----------+----------+---------------+---------+----------+-------------------+------------+-------------+
| 1 | SIMPLE | test02 | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 9 | 100.00 | where の使用 |
| 1 | 削除 | test01 | NULL | ref | a | a | 5 | dbtest01.test02.b | 1 | 100.00 | NULL |
+----+-------------+---------+-----------+----------+---------------+---------+----------+-------------------+------------+-------------+
セットに2行(0.01秒)

実行は非常に高速です。root@localhost [dbtest01]>delete test01.* from test01 join test02 on test01.a=test02.b and test02.id<10;
クエリは正常、9 行が影響を受けました (0.01 秒)

root@localhost [dbtest01]>test01 から test01.* を選択し、test01.a=test02.b および test02.id<10 で test02 を結合します。
空のセット (0.00 秒)

次のテーブル実行では、非常に遅いフルテーブルスキャンが必要です。基本的には、テーブル test01 でフルテーブルスキャンを実行します。

root@lcalhost [dbtest01]>desc delete FROM test01 WHERE id IN (SELECT id FROM test02 WHERE id='350000');
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+-------------+
| 1 | DELETE | test01 | NULL | ALL | NULL | NULL | NULL | NULL | 499343 | 100.00 | where の使用 |
| 2 | 従属サブクエリ | test02 | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | インデックスを使用 |
+----+--------------------+---------+-----------+---------+---------------+----------+---------+----------+-----------+------------+-------------+
セット内の 2 行 (0.00 秒)

ただし、join を使用すると、効率は非常に高くなります。

root@localhost [dbtest01]>desc delete test01.* FROM test01 inner join test02 WHERE test01.id=test02.id and test02.id=350000;
+----+-------------+---------+-----------+---------+---------------+---------+--------+----------+-----------+-------------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+---------+-----------+---------+---------------+---------+--------+----------+-----------+-------------+
| 1 | 削除 | test01 | NULL | const | プライマリ | プライマリ | 4 | const | 1 | 100.00 | NULL |
| 1 | SIMPLE | test02 | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | インデックスを使用 |
+----+-------------+---------+-----------+---------+---------------+---------+--------+----------+-----------+-------------+
セットに2行(0.01秒)

 
root@localhost [dbtest01]> desc test01 から test01.* を削除し、test01.a=test02.b および test02.id=350000 で test02 を結合します。
+----+-------------+---------+-----------+--------+---------------+---------+-------+-------+------+------+------+------+
| id | select_type | テーブル | パーティション | タイプ | 可能なキー | キー | キー長 | ref | 行 | フィルター済み | 追加 |
+----+-------------+---------+-----------+--------+---------------+---------+-------+-------+------+------+------+------+
| 1 | SIMPLE | test02 | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
| 1 | 削除 | test01 | NULL | ref | a | a | 5 | const | 1 | 100.00 | NULL |
+----+-------------+---------+-----------+--------+---------------+---------+-------+-------+------+------+------+------+
セット内の 2 行 (0.00 秒)

参考資料:

https://www.cnblogs.com/zhengyun_ustc/p/slowquery1.html
https://www.jianshu.com/p/3989222f7084
https://dev.mysql.com/doc/refman/5.6/en/サブクエリ最適化.html

これで、MySQL のサブクエリの最適化における選択の実装に関するこの記事は終了です。MySQL のサブクエリの最適化における選択に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL 選択最適化ソリューションに関する簡単な説明
  • MySQL で結果を選択して更新を実行する例のチュートリアル
  • MySQLの読み書き分離により挿入後にデータが選択されなくなる問題を解決
  • MySQL SELECT文の実行方法
  • MySQL 学習ノート: 完全な SELECT ステートメントの使用例と詳細な説明
  • MySQL の選択、挿入、更新バッチ操作ステートメントのコード例
  • MySQL SELECT実行順序の簡単な理解
  • 更新とデータ整合性処理のためのMySQLトランザクション選択の説明
  • MySQL における単一テーブルと複数テーブル、およびビューと一時テーブルに対する Update と Select の違い
  • MySQL セレクトキャッシュメカニズムの使用に関する詳細な説明
  • MySql データベースでの Select の使用法の概要
  • MySQLでSELECT文が実行される仕組み

<<:  Dockerデータのバックアップとリカバリプロセスの詳細な説明

>>:  Dockerコンテナ接続実装手順の分析

推薦する

MySQL 実践演習 シンプルなライブラリ管理システム

目次1. ソート機能2. データベースを準備する3. データベースに関連するエンティティクラスの構築...

MySQL で数千万のテストデータを含むテストデータベースを作成する方法

場合によっては、MySQL が公式に提供しているテスト ライブラリに基づいてテスト データを作成し、...

Vue2 キューブUI 時間セレクターの詳細な説明

目次序文1. 需要と効果必要効果2. コードの実装index.vue(html)日付方法テスト結果3...

Hadoop 2.x と 3.x の 22 ポイントの比較、Hadoop 3.x の 2.x に対する改善点

質問ガイド1. Hadoop 3.x はどのようにして障害を許容するのでしょうか? 2. Hadoo...

Centos7 ベースの Nginx Web サイト サーバーの構築の詳細説明 (仮想 Web ホストの構成を含む)

1. Nginx サービス基盤Nginx (エンジン x) は、パフォーマンスの最適化のために特別...

SSDストレージを有効にしたMySQLインスタンスの詳細な説明

SSDストレージを有効にしたMySQLインスタンスの詳細な説明特に OS と MySQL が同じディ...

MySQL 制約の超詳細な説明

目次MySQL 制約操作1. 非ヌル制約2. ユニーク制約3. 主キー制約4. 外部キー制約5. カ...

Centos7.4 システムに yum ソースから mysql 5.6 をインストールする

システム環境: centos7.4 1. データベースがインストールされているかどうかを確認します。...

vscodeで保存した後のHTML自動フォーマットの問題を解決する

vsCode のバージョンは最近更新され、現在のバージョン番号は 1.43 です。実際、vsCode...

一般的なメールボックスで正常に表示できる HTML メールを作成するためのヒント

HTML メールを送信するためのヒント: スタイルを使用してインライン CSS を記述する、使用する...

MySQL 5.7.18 リリース インストール ガイド (bin ファイル バージョンを含む)

インストール プロセスは、コンパイル手順を除いて、基本的にソース バージョンと同じです。この記事では...

CSS3 を使用してピカチュウのアニメーション壁紙を作成する例

文章さて、次はレンダリングを見せましょう。画像を見て初めて理解することに興味が湧くでしょう。そうでな...

URLに基​​づいてリクエストを転送するnginxの実装の実践経験

序文これは fastdfs を使用してイントラネット外部に展開された分散ファイルシステムであるためで...

CSS3はアニメーション効果を実現するためにvar()とcalc()関数を使用する。

ナレッジポイントをプレビューします。アニメーションフレーム背景グラデーションvar() と calc...

Portainer を使用して複数の Docker コンテナ環境を管理する方法を説明します。

目次Portainerは複数のDockerコンテナ環境を管理します2. Dockerを管理する2.1...