【データベース】MySQLクエリーの最適化
公衆番号へようこそ:【
愛コード】
バックグラウンドの返信が必要な場合
2019贈呈
1 Tの学习资料よ!!
背景
この急速な発展の時代に、時間はますます重要になって、流れも非常に速くて、一部の人は大きくなって、一部の人は年を取っています.うっかりして、2019はもう3分の1を過ぎてしまいました.この4ヶ月の収穫を振り返って、何を知っていますか?メッセージを共有してくださいね.
**本題に戻ります:MySQLの検索はどのように更に速くて、更に合理的ですか?インデックス以外に学ぶことはありますか?**
げんり
何かをよりよく学ぶには、その原理と働き方から身につけやすい.道理は君たちはみな知っているから,私はくだらないことを言わない.
MySQLはクエリーリクエストを送信しますが、いったいどんな仕事をしましたか?
次の図はMySQLクエリ実行フローチャートです.クライアントは、サーバにクエリーを送信します. サーバは、クエリー・キャッシュを確認し、キャッシュにヒットした場合、すぐにクエリーのキャッシュ内の結果を返します.そうでなければ次の段階に進みます.
3.サービス側はSQL解析、前処理を行い、オプティマイザによって対応する実行計画を生成する.4.MySQLは、オプティマイザが生成した実行計画に基づいて、ストレージエンジンのAPIを呼び出してクエリーを実行します.5.結果をクライアントに返します.
MySQLクエリーが遅くなったのは何ですか?
MySQLの場合、クエリのオーバーヘッドを測定する最も簡単な3つの指標は次のとおりです.応答時間 スキャンの行数 が返す行数 クエリーのオーバーヘッドを完璧に測定できる指標はありませんが、MySQLが内部でクエリーを実行する際にどのくらいのデータにアクセスする必要があるかをほぼ反映し、クエリーの実行時間を推定することができます.
クエリが遅い原因は、クエリの余分なデータが多すぎるためです.よくある理由は次のとおりです.
1.不要なレコードを問い合せます.
2.複数のテーブルが関連付けられている場合、すべての列を返します.
3.常にすべての列を取り出す
一般的な最適化テクニック
1.インデックス
最も簡単で効果的な方法は、条件にインデックス(プライマリ・キー・インデックス、通常のインデックス、一意のインデックスなど)を追加することです.注意:インデックスは別のスペースストレージを開くため、インデックスを追加する必要はありません.
2.関連サブクエリ
MySQLのサブクエリの実装は非常に悪いです.例えば次の
MySQLはIN()リストのオプションに特別な最適化ポリシーを持っており、MySQLはサブクエリを先に実行してauthorを含むすべてのものを返すと一般的に考えられています.idが1のbook_id.
MySQLの実行時にそうしたいかもしれません.
ただし、MySQLは関連する外部テーブルをサブクエリに圧縮します.次のようになります.
理由:サブクエリにbook_が必要なためid、だからMySQLは先にこのサブクエリを実行することができないと思って、先にbookに対して全表スキャンを行って、それからbook_によってidはサブクエリを行う.具体的にはEXPLAINのSQLで分析できます.
提案:1.サブクエリの代わりに左外部ジョイン(LEFTOUTER JOIN)を使用します.
影響要因:データテーブルの配置位置など、具体的な適用シーンは、どの性能が良いかを自分でexplainするしかありません.
2.ONまたはUSING句の列にインデックスがあることを確認し、インデックスを作成する際に関連する順序を考慮します.
3.UNION使用
UNIONの各句がLIMITによって結果セットの一部のみを取ることができれば,あるいは結果セットを順番に並べてからマージすることができればよい.最初の例:authorテーブルとuserテーブルの両方のテーブルが一時テーブルに格納され、最初の20個が一時テーブルから取り出されます.
上記のように、かなり改善されています.
4.最大値と最小値
たとえば、最小値を求める第1のシナリオ:
2つ目のシナリオ:
1つ目のシナリオと比較すると、効果は実際には同じですが、それらの性能は少し異なります.具体的には、自分の具体的なシーンを分析し、選択してください.
5.COUNT()クエリー
たとえば、記事idが25より大きい数を統計したい場合は、次のようにします.
もう1つの考え方は、まず文章の総数を調べて、25以下の数を減らすことができます.考えを提供するだけで、具体的な効果はやはりあなたの具体的な状況で、自分で比較して、優を選んで選択します.
余談:色の異なる商品の数を区別する必要がある場合は、次のようにすることができます.
6.GROUP BYとDISTINCT
最適化の最も効果的な方法は、インデックスを使用することです.しかしGROUP BYが間違っている場合があり、インデックスは無効になります.たとえば、2つの個別のインデックスを1つの組合せインデックスに結合します.すなわち、where条件フィールドのインデックスとgroupbyのパケットフィールドのインデックスを1つに結合します.
解決方法:この関数インデックスを参照
7.limitページング
次のクエリは、非常に一般的です.
しかし、この表が大きい場合、この50が100654になると、ここMySQLは100654+5個のデータをスキャンし、100654個を捨てて最後の5個だけ行きます.1つの考え方:
このアイデアは、関連付けを遅らせることでクエリーの効率を大幅に向上させ、MySQLができるだけ少ないページをスキャンできるようにすることです.アクセスが必要なレコードを取得した後、さらに関連付けられたカラムは、元のテーブルで必要なすべてのカラムをクエリーします.以上は必ずしもあなたに合っているわけではありませんが、具体的にはexplainの比較が必要です.
まとめ:全体的には、できるだけ全テーブルスキャンを少なくし、できるだけインデックスを使用して最適化します.最後に、実際のシーンでexplainでより良いsqlソリューションがあるかどうかを分析することが多い.
インデックスが無効になるシーン
1.暗黙的な変換によりインデックスが失効する.この点は重視すべきである.開発中によく犯す間違いでもある.テーブルのフィールドtu_mdnはvarchar 2(20)と定義が、クエリ時にこのフィールドをnumberタイプとしてwhere条件でOracleに渡すと、インデックスが失効する.
2.インデックス列の演算によるインデックス失効とは、インデックス列の演算*(+、-、/、!)を含む
3.内部関数を使用するとインデックスが無効になる.このような場合には、関数ベースのインデックスを作成する必要がある.
4.空の変数値を比較演算子(シンボル)と直接比較しないでください.変数が空の場合は、IS NULLまたはIS NOT NULLを使用して比較するか、ISNULL関数を使用します.
5.SQLコードで二重引用符を使用しないでください.文字定数は単一引用符を使用するためです.オブジェクト名を限定する必要がない場合は、(ANSI SQL規格ではない)カッコを使用して名前を囲むことができます.
6.次の使用はインデックスを無効にします.使用しないでください.
a.<>、not in、not exist、!=
b. like "%_"パーセンテージは以前(インデックス作成時にreverse(columnName)という方法で処理できます)
c.複合インデックス内の第1位置以外のインデックス列を単独で参照する.オプティマイザは、常にインデックスの最初のカラムを使用する必要があります.インデックスが複数のカラムに確立されている場合、最初のカラムがwhere句で参照されている場合にのみ、インデックスの使用を選択します.
d.文字型フィールドが数字の場合where条件に引用符を付けない.
e.変数がtimes変数である、テーブルのフィールドがdate変数である場合.あるいは逆の状況.
一時的にこんなにたくさん統計して、もっとあれば後で補充します.
MySQLのEXPLAINの使用
EXPLAINはSQLの実行状況分析を分析するためのものです
EXPLAINコマンドの出力内容は以下の通りです.
各列の意味は次のとおりです. id:SELECTクエリの識別子.SELECTごとに一意の識別子が自動的に割り当てられます. select_type:SELECT検索のタイプ. table:クエリーされたテーブル partitions:一致するパーティション type:joinタイプ possible_keys:今回のクエリで選択可能なインデックス key:今回のクエリで正確に使用するインデックス. ref:keyとともに使用されるフィールドまたは定数は です. rows:このクエリが合計何行スキャンされたかを表示します.これは推定値です. filtered:このクエリ条件でフィルタされたデータの割合を示す . extra:追加情報 もっと詳しくはこの「性能最適化神器Explain使用分析」または「高性能MySQL」を参照してください.
まとめ
クエリの最適化の目的は、結果を迅速に得ることです.SQLを書くたびに、次の点を考えなければなりません.テーブル全体のクエリーが必要かどうか、および返されるデータが適切かどうか. インデックスが必要かどうか、インデックスが適切かどうか. より良い解決策があるかどうか.
最後に
Java、ビッグデータに興味があればQRコードを長く押して注目してください.私はあなたたちに価値をもたらすように努力します.あなたに少しでも役に立つと思う人は、「いいね」や「転送」を手伝ってください.公式アカウント「愛コード」に注目し、2019に返信するには関連資料がありますよ.
愛コード】
バックグラウンドの返信が必要な場合
2019贈呈
1 Tの学习资料よ!!
背景
この急速な発展の時代に、時間はますます重要になって、流れも非常に速くて、一部の人は大きくなって、一部の人は年を取っています.うっかりして、2019はもう3分の1を過ぎてしまいました.この4ヶ月の収穫を振り返って、何を知っていますか?メッセージを共有してくださいね.
**本題に戻ります:MySQLの検索はどのように更に速くて、更に合理的ですか?インデックス以外に学ぶことはありますか?**
げんり
何かをよりよく学ぶには、その原理と働き方から身につけやすい.道理は君たちはみな知っているから,私はくだらないことを言わない.
MySQLはクエリーリクエストを送信しますが、いったいどんな仕事をしましたか?
次の図はMySQLクエリ実行フローチャートです.
3.サービス側はSQL解析、前処理を行い、オプティマイザによって対応する実行計画を生成する.4.MySQLは、オプティマイザが生成した実行計画に基づいて、ストレージエンジンのAPIを呼び出してクエリーを実行します.5.結果をクライアントに返します.
MySQLクエリーが遅くなったのは何ですか?
MySQLの場合、クエリのオーバーヘッドを測定する最も簡単な3つの指標は次のとおりです.
クエリが遅い原因は、クエリの余分なデータが多すぎるためです.よくある理由は次のとおりです.
1.不要なレコードを問い合せます.
2.複数のテーブルが関連付けられている場合、すべての列を返します.
3.常にすべての列を取り出す
一般的な最適化テクニック
1.インデックス
最も簡単で効果的な方法は、条件にインデックス(プライマリ・キー・インデックス、通常のインデックス、一意のインデックスなど)を追加することです.注意:インデックスは別のスペースストレージを開くため、インデックスを追加する必要はありません.
2.関連サブクエリ
MySQLのサブクエリの実装は非常に悪いです.例えば次の
SELECT * FROM book WHERE book_id IN (SELECT book_id FROM author WHERE author_id = 1)
MySQLはIN()リストのオプションに特別な最適化ポリシーを持っており、MySQLはサブクエリを先に実行してauthorを含むすべてのものを返すと一般的に考えられています.idが1のbook_id.
MySQLの実行時にそうしたいかもしれません.
SELECT GROUP_CONCAT(book_id) FROM author WHERE author_id = 1
SELECT * FROM book WHERE book_id IN (1,21,3,45,656,766,213,123)
ただし、MySQLは関連する外部テーブルをサブクエリに圧縮します.次のようになります.
SELECT * FROM book WHERE EXISTS
(SELECT * FROM author WHERE author_id = 1 AND book.book_id = author.book_id)
理由:サブクエリにbook_が必要なためid、だからMySQLは先にこのサブクエリを実行することができないと思って、先にbookに対して全表スキャンを行って、それからbook_によってidはサブクエリを行う.具体的にはEXPLAINのSQLで分析できます.
提案:1.サブクエリの代わりに左外部ジョイン(LEFTOUTER JOIN)を使用します.
SELECT * from book LEFT OUTER JOIN author USING(book_id) WHERE author.author_id = 1
影響要因:データテーブルの配置位置など、具体的な適用シーンは、どの性能が良いかを自分でexplainするしかありません.
2.ONまたはUSING句の列にインデックスがあることを確認し、インデックスを作成する際に関連する順序を考慮します.
3.UNION使用
UNIONの各句がLIMITによって結果セットの一部のみを取ることができれば,あるいは結果セットを順番に並べてからマージすることができればよい.最初の例:authorテーブルとuserテーブルの両方のテーブルが一時テーブルに格納され、最初の20個が一時テーブルから取り出されます.
(SELECT first_name FROM author ORDER BY last_name)
UNION ALL
(SELECT first_name FROM user ORDER BY last_name)
LIMIT 20
上記のように、かなり改善されています.
(SELECT first_name FROM author ORDER BY last_name LIMIT 20)
UNION ALL
(SELECT first_name FROM user ORDER BY last_name LIMIT 20)
LIMIT 20
4.最大値と最小値
たとえば、最小値を求める第1のシナリオ:
SELECT MIN(id) FROM article WHERE author = 'zero'
2つ目のシナリオ:
SELECT id FROM article USE INDEX(PRIMARY) WHERE author = 'zero' LIMIT 1
1つ目のシナリオと比較すると、効果は実際には同じですが、それらの性能は少し異なります.具体的には、自分の具体的なシーンを分析し、選択してください.
5.COUNT()クエリー
たとえば、記事idが25より大きい数を統計したい場合は、次のようにします.
EXPLAIN SELECT COUNT(*) FROM article WHERE id >25
もう1つの考え方は、まず文章の総数を調べて、25以下の数を減らすことができます.考えを提供するだけで、具体的な効果はやはりあなたの具体的な状況で、自分で比較して、優を選んで選択します.
EXPLAIN SELECT (SELECT COUNT(*) FROM article) - COUNT(*) FROM article WHERE id <=25
余談:色の異なる商品の数を区別する必要がある場合は、次のようにすることができます.
seelct count(color = 'blue' OR NULL) as blue,COUNT(color = 'red' OR NULL) AS RED FROM items
6.GROUP BYとDISTINCT
最適化の最も効果的な方法は、インデックスを使用することです.しかしGROUP BYが間違っている場合があり、インデックスは無効になります.たとえば、2つの個別のインデックスを1つの組合せインデックスに結合します.すなわち、where条件フィールドのインデックスとgroupbyのパケットフィールドのインデックスを1つに結合します.
解決方法:この関数インデックスを参照
7.limitページング
次のクエリは、非常に一般的です.
select film_id,description from film order by title limit 50,5;
しかし、この表が大きい場合、この50が100654になると、ここMySQLは100654+5個のデータをスキャンし、100654個を捨てて最後の5個だけ行きます.1つの考え方:
select film_id,description from film inner join (select film_id from film order by title limit 50,5) as lim USING(film_id);
このアイデアは、関連付けを遅らせることでクエリーの効率を大幅に向上させ、MySQLができるだけ少ないページをスキャンできるようにすることです.アクセスが必要なレコードを取得した後、さらに関連付けられたカラムは、元のテーブルで必要なすべてのカラムをクエリーします.以上は必ずしもあなたに合っているわけではありませんが、具体的にはexplainの比較が必要です.
まとめ:全体的には、できるだけ全テーブルスキャンを少なくし、できるだけインデックスを使用して最適化します.最後に、実際のシーンでexplainでより良いsqlソリューションがあるかどうかを分析することが多い.
インデックスが無効になるシーン
1.暗黙的な変換によりインデックスが失効する.この点は重視すべきである.開発中によく犯す間違いでもある.テーブルのフィールドtu_mdnはvarchar 2(20)と定義が、クエリ時にこのフィールドをnumberタイプとしてwhere条件でOracleに渡すと、インデックスが失効する.
:select * from test where tu_mdn=13333333333;
:select * from test where tu_mdn='13333333333';
2.インデックス列の演算によるインデックス失効とは、インデックス列の演算*(+、-、/、!)を含む
:select * from test where id-1=9;
:select * from test where id=10;
3.内部関数を使用するとインデックスが無効になる.このような場合には、関数ベースのインデックスを作成する必要がある.
// :
select * from test where round(id)=10; // , id
// :
create index test_id_fbi_idx on test(round(id));
//
select * from test where round(id)=10;
4.空の変数値を比較演算子(シンボル)と直接比較しないでください.変数が空の場合は、IS NULLまたはIS NOT NULLを使用して比較するか、ISNULL関数を使用します.
5.SQLコードで二重引用符を使用しないでください.文字定数は単一引用符を使用するためです.オブジェクト名を限定する必要がない場合は、(ANSI SQL規格ではない)カッコを使用して名前を囲むことができます.
6.次の使用はインデックスを無効にします.使用しないでください.
a.<>、not in、not exist、!=
b. like "%_"パーセンテージは以前(インデックス作成時にreverse(columnName)という方法で処理できます)
c.複合インデックス内の第1位置以外のインデックス列を単独で参照する.オプティマイザは、常にインデックスの最初のカラムを使用する必要があります.インデックスが複数のカラムに確立されている場合、最初のカラムがwhere句で参照されている場合にのみ、インデックスの使用を選択します.
d.文字型フィールドが数字の場合where条件に引用符を付けない.
e.変数がtimes変数である、テーブルのフィールドがdate変数である場合.あるいは逆の状況.
一時的にこんなにたくさん統計して、もっとあれば後で補充します.
MySQLのEXPLAINの使用
EXPLAINはSQLの実行状況分析を分析するためのものです
EXPLAINコマンドの出力内容は以下の通りです.
mysql> explain select * from user_info where id = 2\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: user_info
partitions: NULL
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 8
ref: const
rows: 1
filtered: 100.00
Extra: NULL
1 row in set, 1 warning (0.00 sec)
各列の意味は次のとおりです.
まとめ
クエリの最適化の目的は、結果を迅速に得ることです.SQLを書くたびに、次の点を考えなければなりません.
最後に
Java、ビッグデータに興味があればQRコードを長く押して注目してください.私はあなたたちに価値をもたらすように努力します.あなたに少しでも役に立つと思う人は、「いいね」や「転送」を手伝ってください.公式アカウント「愛コード」に注目し、2019に返信するには関連資料がありますよ.