SQL 最適化 21 コンボ + マインドマップ

1. クエリ SQL に select * を使用するのではなく、特定のフィールドを使用するようにしてください。

1.反例

SELECT * FROM user

2、正例

SELECT id,username,tel FROM user

3.理由

  1. リソースを節約し、ネットワーク オーバーヘッドを削減します。
  2. カバリング インデックスを使用して、返されるテーブルを減らし、クエリの効率を向上させることができます。

注意:为节省时间,下面的样例字段都用*代替了。

2. 条件を接続するために where 句で or を使用しない

1.反例

SELECT * FROM user WHERE id=1 OR salary=5000

2、正例

(1)ユニオンオールを使う

SELECT * FROM user WHERE id=1 
UNION ALL
SELECT * FROM user WHERE salary=5000

(2) 2 つの sql 書き込みを分離する

SELECT * FROM user WHERE id=1

SELECT * FROM user WHERE salary=5000

3.理由

  1. 使用orすると、インデックスが無効になり、テーブル全体がスキャンされる可能性があります。
  2. orインデックスがない場合は、インデックスに移動salaryたと見なされますが、クエリ条件に達すると、テーブル全体のスキャンを実行する必要があります。idsalary
  3. つまり、プロセス全体で 3 つのステップが必要です。テーブル全体のスキャン + インデックス スキャン + マージです。最初に全テーブル スキャンを実行する場合は、直接スキャンすることで実行できます。
  4. オプティマイザはありmysqlますが、効率とコストを考慮して、or特定の条件下でインデックスが失敗する場合があります。

3.文字列型の代わりに数値を使用してみてください

1、正例

  1. 主キー (id):primary key最初に数値型を使用intし、tinyint
  2. 性別 (性別): 女性の場合は 0、男性の場合は 1; データベースにはブール型がないため、使用することをmysqlお勧めしますtinyint

2.理由

  1. エンジンは、クエリと接続を処理するときに、文字列内の各文字を 1 つずつ比較するためです。
  2. デジタル タイプの場合、必要な比較は 1 回だけです。
  3. 文字はクエリと結合のパフォーマンスを低下させ、ストレージのオーバーヘッドを増加させます。

4 番目に、char の代わりに varchar を使用します。

1.反例

`address` char(100) DEFAULT NULL COMMENT '地址'

2、正例

`address` varchar(100) DEFAULT NULL COMMENT '地址'

3.理由

  1. varchar可変長フィールドは、データコンテンツの実際の長さに応じて格納され、ストレージスペースが小さいため、ストレージスペースを節約できます。
  2. char宣言されたサイズに従って保存し、不十分な場合はスペースを埋めます。
  3. 次に、クエリの場合、比較的小さなフィールドで検索する方が効率的です。

5. 技術拡張、char と varchar2 の違いは?

1.char長さは固定ですがvarchar2、長さは変更できます。

たとえば、文字列を格納すると、格納する文字“101”char(10)10 バイト (7 つのヌル文字を含む) を占め、データベースではスペースで占められ、同じvarchar2(10)長さで 3 バイトしか占有されず、10 はちょうど最大値、10 文字未満を保存する場合は、実際の長さで保存します。

2.char効率は よりわずかに高くなりvarchar2ます。

3.いつchar、いつ使用するのvarchar2ですか?

charvarchar2は相反する一体性の対であり、両者は補完的であり、効率比はスペースを節約するvarchar2よりもわずかに悪くなります。効率を上げたい場合は、少しスペースを犠牲にしなければなりません。これは、データベース設計でよく言われることです。」スペースと交換する効率」。charchar

varchar2スペースをchar節約できますが、varchar2列が頻繁に変更され、変更されたデータの長さが毎回異なる場合、これにより「行の移行」という現象が発生し、冗長な I/O が発生するため、データベース設計で回避する必要があります。 . 、この場合char代わりに. フィールドに移動すると空白が自動的に埋められるため、空白も自動的に埋められますが空白は削除されないため、 query と入力するときにそれらを使用することを忘れないでください。これがこの記事を書く理由です.varchar2charinsertcharselectchartrim

開発者がrpad()トリックの使用を改良して、バインド変数をフィールドと比較できる型に変換する場合char(もちろん、バインド変数を設定する方がtrim、データベースの列を切り詰めるよりも優れています。関数を列に適用すると、trim簡単に列の既存のインデックスを使用することはできません)、時間の経過に伴う列の長さの変化を考慮する必要がある場合があります。フィールドのサイズが変更されると、フィールド幅を変更する必要があるため、アプリは影響を受けます。

上記の理由により、固定幅のストレージ スペースによってテーブルや関連するインデックスが通常よりもはるかに大きくなり、バインド変数の問題が発生する可能性があるため、char 型はどのような場合でも避ける必要があります。

6. null の代わりにデフォルト値を使用します。

1.反例

SELECT * FROM user WHERE age IS NOT NULL

2、正例

SELECT * FROM user WHERE age>0

3.理由

  1. インデックスが使用されない、またはis null使用されないという意味ではありませんが、これはバージョンとクエリのコストに関連しています。is not nullmysql
  2. インデックスを使用するコストが、インデックスを使用しないコストよりも高いことがわかった場合mysql、オプティマイザはインデックスを破棄します。これらの条件!=,<>,is null,is not nullは、多くの場合、インデックスを無効にするものと見なされます。
  3. 実際、一般にクエリのコストは高く、オプティマイザーは自動的にインデックスを破棄します。
  4. 値をデフォルト値に置き換えるnullと、インデックスに移動できることが多く、同時に意味が比較的明確になります。

7. where 句で != または <> 演算子を使用しない

1.反例

SELECT * FROM user WHERE salary!=5000

SELECT * FROM user WHERE salary<>5000

2.理由

  1. を使用する!=<>、インデックスが無効になる可能性があります
  2. where句で!=OR<>演算子を使用しないようにしてください。そうしないと、エンジンがインデックスの使用を断念し、完全なテーブル スキャンを実行します。
  3. ビジネスの優先順位を達成するには、本当に方法はありません。使用するしかありません。使用することは不可能ではありません。

8、内結合、左結合、右結合、内結合優先

3 つの結合の結果が同じ場合は、内部結合が優先されます。左結合を使用する場合は、左テーブルをできるだけ小さくする必要があります。

  • 内部結合 内部結合では、2 つのテーブルで完全に一致する結果セットのみが保持されます。
  • 左結合は、右側のテーブルに一致するレコードがない場合でも、左側のテーブルのすべての行を返します。
  • 右側の結合は、左側のテーブルに一致するレコードがない場合でも、右側のテーブルのすべての行を返します。

なんで?

  • 内部結合が等結合の場合、返される行数は比較的少ないため、パフォーマンスは比較的良くなります。
  • 左結合を使用すると、左テーブルのデータ結果は可能な限り小さくなり、条件は可能な限り左側に配置されます。つまり、返される行数が比較的少なくなる可能性があります。
  • これが mysql の最適化の原則です。つまり、小さなテーブルが大きなテーブルを駆動し、小さなデータ セットが大きなデータ セットを駆動するため、パフォーマンスが向上します。

9、ステートメントによってグループの効率を向上させる

1.反例

最初にグループ化してからフィルタリングする

select job, avg(salary) from employee 
group by job
having job ='develop' or job = 'test';

2、正例

最初にフィルタリングし、後でグループ化する

select job,avg(salary) from employee 
where job ='develop' or job = 'test' 
group by job;

3.理由

ステートメントを実行する前に不要なレコードを除外できます

10.テーブルを空にするときは、最初に切り捨てを使用します

truncate tablewhereのないステートメントと機能的に同じdeleteです: どちらもテーブル内のすべての行を削除します。ただしtruncate tabledeleteより高速で、システムおよびトランザクション ログ リソースの使用量が少なくなります。

deleteこのステートメントは、一度に 1 行ずつ削除し、削除された行ごとにトランザクション ログにエントリを記録します。truncate tableデータは、テーブル データの格納に使用されたデータ ページを解放することによって削除され、ページの解放はトランザクション ログに記録されるだけです。

truncate tableテーブル内のすべての行を削除しますが、テーブル構造とその列、制約、インデックスなどは変更されません。新しい行の識別に使用されるカウント値は、この列のシードにリセットされます。ID カウント値を保持する場合は、代わりに DELETE を使用してください。テーブル定義とそのデータを削除する場合は、drop tableステートメント。

foreign key制約によって参照されるテーブルの場合truncate tablewhere句DELETE ステートメントを使用することはできません。truncate tableログに記録されないため、トリガーをアクティブにすることはできません。

truncate tableインデックス付きビューに参加しているテーブルには使用できません。

11. delete または update ステートメントを操作し、制限を追加または一括で削除する

1. 間違った SQL を書くコストを削減する

テーブルのデータを消去するのは些細なことではなく、片手の揺れがなくなり、データベースを削除して逃げる?制限を追加すると、データを誤って削除した場合に失われるのはデータの一部だけであり、binlog ログからすばやく復元できます。

2. SQL 効率が高くなる可能性が高い

SQL に追加されましlimit 1た。最初のターゲットがヒットした場合、ヒットしreturnなかった場合limit、テーブルのスキャンを続行します。

3.長時間の取引を避ける

delete実行中ageにインデックスが追加されると、MySQL は関連するすべての行に書き込みロックとギャップ ロックを追加し、実行に関連するすべての行がロックされます. 削除の数が多い場合は、関連するサービスの使用不可に直接影響します. .

4.データ量が多いとCPUがいっぱいになりやすい

大量のデータを削除する場合は、制限を追加してレコード数を制限しないでください。簡単にいっぱいcpuになり、削除がますます遅くなります。

5. テーブルのロック

一度に大量のデータを削除するとロックテーブル、ロック待ちタイムアウト超過エラーが発生する場合があるため、一括で運用することを推奨します。

12. UNION 演算子

UNION重複レコードはテーブル リンク後に除外されるため、テーブル リンク後に結果セットが並べ替えられ、重複レコードが削除され、結果が返されます。
ほとんどの実用的なアプリケーションでは、重複レコードは生成されません。最も一般的なのはプロセス テーブルと履歴テーブルUNIONです。お気に入り:

select username,tel from user
union
select departmentname from department

この SQL は、最初に実行時に 2 つのテーブルの結果を取得し、次に並べ替え領域を使用して並べ替えを行い、重複するレコードを削除し、最後に結果セットを返します。
推奨される解決策:UNION ALL演算子置換UNIONを使用します。これUNION ALLは、操作が 2 つの結果を単純に組み合わせて返されるためです。

十三、一括挿入性能向上

1. 複数の提出

INSERT INTO user (id,username) VALUES(1,'哪吒编程');

INSERT INTO user (id,username) VALUES(2,'妲己');

2.一括提出

INSERT INTO user (id,username) VALUES(1,'哪吒编程'),(2,'妲己');

3.理由

新たに追加された SQL はデフォルトでトランザクション制御を備えているため、トランザクションごとにオープンしてコミットするのに対し、バッチ処理は一度にオープンしてコミットするトランザクションであり、効率が大幅に向上し、一定の桁数に達します。

14. テーブル接続とインデックスが多すぎてはいけません。通常は 5 以内です。

1. テーブル接続は多すぎてはいけません。通常は 5 未満です。

  1. 関連付けられたテーブルの数が多いほど、コンパイル時間とオーバーヘッドが大きくなります
  2. 一時テーブルは毎回連想メモリに生成されます
  3. 接続テーブルは、より読みやすい小さな実行に分割する必要があります
  4. データを取得するために多くのテーブルを結合する必要がある場合、それは設計が悪いことを意味します
  5. アリの仕様では、複数のテーブルで 3 つ以下のテーブルをクエリすることが推奨されています。

2. インデックスは多すぎてはいけません。通常は 5 未満です。

  1. インデックスが多ければ多いほど、クエリの効率は向上しますが、挿入と更新の効率は低下します。
  2. インデックスは、データを格納できるテーブルとして理解でき、そのデータはスペースを占有します。
  3. インデックス テーブルのデータは並べ替えられますが、並べ替えには時間がかかります。
  4. insertデータ量が膨大な場合、再構築によってレコードの順序が変更されるupdateため、特定の状況に応じて、インデックスの構築を慎重に検討する必要があります。
  5. テーブル内のインデックスの数は 5 を超えてはなりません。インデックスが多すぎる場合は、いくつかのインデックスが存在するかどうかを考慮する必要があります。

15. インデックス付きの列で組み込み関数を使用しない

1.反例

SELECT * FROM user WHERE DATE_ADD(birthday,INTERVAL 7 DAY) >=NOW();

2、正例

SELECT * FROM user WHERE  birthday >= DATE_ADD(NOW(),INTERVAL 7 DAY);

3.理由

インデックス付きの列で組み込み関数を使用すると、インデックスが無効になります。

16. 総合指数

並べ替えるときは、インデックス内の 1 つの列のみを並べ替える場合でも、複合インデックス内の列の順序に従って並べ替える必要があります。そうしないと、並べ替えのパフォーマンスが低下します。

create index IDX_USERNAME_TEL on user(deptid,position,createtime);
select username,tel from user where deptid= 1 and position = 'java开发' order by deptid,position,createtime desc; 

実際には、deptid= 1 and position = 'java开发'条件を満たすし、createtime の降順で並べ替えますが、createtime desc による書き込み順のパフォーマンスはよくありません。

セブンティーン、総合指数の一番左の特徴

1.複合インデックスを作成する

ALTER TABLE employee ADD INDEX idx_name_salary (name,salary)

2. 複合インデックスの左端の機能を満たします。部分的であっても、複合インデックスが有効になります

SELECT * FROM employee WHERE NAME='哪吒编程'

3. 左のフィールドが表示されない場合、左端の特性が満たされていないため、インデックスが無効です

SELECT * FROM employee WHERE salary=5000

4. すべての複合インデックスが使用され、名前と給与が左側の順序で表示され、インデックスが有効になります

SELECT * FROM employee WHERE NAME='哪吒编程' AND salary=5000

5. 一番左の特徴に反しますが、SQL実行時にMySQLが最適化し、最下層が最適化されます

SELECT * FROM employee WHERE salary=5000 AND NAME='哪吒编程'

6.理由

複合インデックスは結合インデックスとも呼ばれます. (k1,k2,k3) のような結合インデックスを作成する場合、(k1)、(k1,k2)、および (k1,k2,k3) の 3 つのインデックスを作成することと同じです。これは左端の一致原理です。

ジョイント インデックスは左端の原則を満たしていないため、通常、インデックスは失敗します。

十八、like文を最適化する

ファジー クエリ (プログラマが好んで使用するものlike)likeは、インデックスを無効にする可能性があります。

1.反例

select * from citys where name like '%大连' (不使用索引)
select * from citys where name like '%大连%' (不使用索引)

2、正例

select * from citys where name like '大连%' (使用索引)

3.理由

  • まず第一に、ファジー クエリを避けるようにしてください. 使用する必要がある場合は、完全なファジー クエリを使用する代わりに、正しいファジー クエリを使用するようにしてくださいlike ‘…%’
  • 左ぼかしlike ‘%...’はインデックスを直接使用することはできませんがreverse + function index、使用できる形式が に変更されlike ‘…%’ます。
  • 完全なファジー クエリは最適化できません。使用する必要がある場合は、検索エンジンを使用することをお勧めします。

19. Explain を使用して SQL 実行計画を分析する

1、タイプ

  1. システム: テーブルには基本的に使用されていない行が 1 つだけあります。
  2. const: テーブルは最大で 1 行のデータと一致し、主キー クエリはより頻繁にトリガーされます。
  3. eq_ref: 前のテーブルの行の組み合わせごとに、このテーブルから行を読み取ります。const 型を除いて、これはおそらく最適な結合型です。
  4. ref: 前のテーブルの行の組み合わせごとに、一致するインデックス値を持つすべての行がこのテーブルから読み取られます。
  5. range: インデックスを使用して行を選択し、指定された範囲の行のみを取得します。=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN、または IN 演算子を使用してキーワード列を定数と比較する場合は、範囲を使用できます。
  6. index: この結合タイプは、索引ツリーのみがスキャンされることを除いて、ALL と同じです。通常、インデックス ファイルはデータ ファイルよりも小さいため、これは ALL よりも高速です。
  7. all: テーブル全体のスキャン。
  8. パフォーマンスのランキング: システム > const > eq_ref > ref > 範囲 > インデックス > すべて。
  9. 実際の SQL 最適化では、最終的に ref または range レベルに到達します。

2. 一般的なキーワード

  • インデックスの使用: インデックス ツリーからのみ情報を取得し、テーブルにクエリを返す必要はありません。
  • where の使用: WHERE 句は、次のテーブルに一致する行、またはクライアントに送信される行を制限するために使用されます。テーブルからすべての行を明示的にフェッチまたはチェックしない限り、Extra 値が Using where ではなく、テーブル結合タイプが ALL または index の場合、クエリでエラーが発生する可能性があります。お問い合わせフォームが必要です。
  • 一時的な使用: mysql は、通常、クエリにさまざまな状況で列をリストできる句が含まGROUP BYれている場合に、結果を保持するために一時テーブルを作成します。ORDER BY

20. その他の最適化方法

1. テーブルを設計するときは、対応するコメントをすべてのテーブルとフィールドに追加します。

2. SQL の記述形式、キーワードのサイズは一貫している必要があり、インデントを使用する必要があります。

3. 重要なデータを変更または削除する前に、まずバックアップしてください。

4. 多くの場合、in の代わりに exists を使用することをお勧めします。

5. where の後ろのフィールドについては、そのデータ型の暗黙的な変換に注意してください。

インデックスは使用されていません

SELECT * FROM user WHERE NAME=110

(1)シングルクォートを付けないと文字列と数値の比較となり、型が一致しないため
(2)MySQLは暗黙の型変換を行い、数値型に変換してから比較する

6. すべての列を次のように定義してみてください。NOT NULL

NOT NULL列はよりスペース効率が高く、NULLはそれが. 列はヌルポインタの問題に注意する必要がある 列を計算して比較するときは、ヌルポインタの問題に注意する必要があります。NULL
NULLNULL

7. 疑似削除デザイン

8. データベースやテーブルの文字セットは可能な限りUTF8を使用する

(1) 文字化けの問題を回避できる。
(2) 異なる文字セットの比較と変換によるインデックスの無効化の問題を回避できます。

9、表からcount(*)を選択;

このような無条件のカウントは、完全なテーブル スキャンを引き起こし、ビジネス上の意味がないため、避ける必要があります。

10.フィールドでの式操作を避ける

(1) SQL 解析中に、フィールドが式に関連している場合、完全なテーブル スキャンが実行されます
(2) フィールドはクリーンで式がなく、インデックスが有効になります

11. 一時テーブルについて

(1) システム テーブル リソースの消費を減らすために、一時テーブルの頻繁な作成と削除を避ける
(2) 新しい一時テーブルを作成するときに、一度に大量のデータが挿入される場合は、create の代わりに select into を使用できます大量のログが発生しないようにするためのテーブル ;
(3) データ量が多くない場合は、システム テーブルのリソースを軽減するために、最初にテーブルを作成してから挿入する必要があります;
(4) 使用する場合ストアド プロシージャの最後ですべての一時テーブルを明示的に削除してください。最初にテーブルを切り捨て、次にテーブルを削除します。これにより、システム テーブルの長期的なロックを回避できます。

12. インデックスは、性別など、大量の繰り返しデータを含むフィールドには適していないため、フィールドを並べ替えるためにインデックスを作成する必要があります

13. 重複排除の個別フィルター フィールドが少ない

  1. 明確なステートメントは、cpuないステートメントよりも時間がかかりますdistinct
  2. 多くのフィールドをクエリする場合、使用されている場合distinct、データベース エンジンはデータを比較し、重複データを除外します。
  3. cpuただし、この比較とフィルタリングのプロセスは、時間などのシステム リソースを消費します。

14. 大規模なトランザクション操作を回避し、システムの同時実行機能を改善するようにしてください

15. すべてのテーブルはInnodbストレージ エンジンを使用する必要があります

Innodb「トランザクションをサポートし、行レベルのロックをサポートし、回復性を向上させる」と、高い並行性の下でパフォーマンスが向上するため、特別な要件 (つまりInnodb、列のストレージ、ストレージ スペースのデータなど、満たすことができない機能) がなければ、パフォーマンスは向上します。など)、すべてのテーブルはInnodbストレージ エンジンを使用する必要があります。

16. カーソルの使用を避ける

カーソルの効率が悪いため、カーソルで操作するデータが10,000行を超える場合は、書き換えを検討する必要があります。

二十一、マインドマップ

「MySql Database Advanced Practice」を5部送付

ここに画像の説明を挿入

より質の高い記事: Nezha Essence 記事の概要

おすすめ

転載: blog.csdn.net/guorui_java/article/details/126542005