目次
-
- 1. クエリ SQL に select * を使用するのではなく、特定のフィールドを使用するようにしてください。
- 2. 条件を接続するために where 句で or を使用しない
- 3.文字列型の代わりに数値を使用してみてください
- 4 番目に、char の代わりに varchar を使用します。
- 5. 技術拡張、char と varchar2 の違いは?
- 6. null の代わりにデフォルト値を使用します。
- 7. where 句で != または <> 演算子を使用しない
- 8、内結合、左結合、右結合、内結合優先
- 9、ステートメントによってグループの効率を向上させる
- 10.テーブルを空にするときは、最初に切り捨てを使用します
- 11. delete または update ステートメントを操作し、制限を追加または一括で削除する
- 12. UNION 演算子
- 十三、一括挿入性能向上
- 14. テーブル接続とインデックスが多すぎてはいけません。通常は 5 以内です。
- 15. インデックス付きの列で組み込み関数を使用しない
- 16. 総合指数
- セブンティーン、総合指数の一番左の特徴
- 十八、like文を最適化する
- 19. Explain を使用して SQL 実行計画を分析する
- 20. その他の最適化方法
- 二十一、マインドマップ
1. クエリ SQL に select * を使用するのではなく、特定のフィールドを使用するようにしてください。
1.反例
SELECT * FROM user
2、正例
SELECT id,username,tel FROM user
3.理由
- リソースを節約し、ネットワーク オーバーヘッドを削減します。
- カバリング インデックスを使用して、返されるテーブルを減らし、クエリの効率を向上させることができます。
注意:为节省时间,下面的样例字段都用*代替了。
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.理由
- 使用
or
すると、インデックスが無効になり、テーブル全体がスキャンされる可能性があります。 or
インデックスがない場合は、インデックスに移動しsalary
たと見なされますが、クエリ条件に達すると、テーブル全体のスキャンを実行する必要があります。id
salary
- つまり、プロセス全体で 3 つのステップが必要です。テーブル全体のスキャン + インデックス スキャン + マージです。最初に全テーブル スキャンを実行する場合は、直接スキャンすることで実行できます。
- オプティマイザはあり
mysql
ますが、効率とコストを考慮して、or
特定の条件下でインデックスが失敗する場合があります。
3.文字列型の代わりに数値を使用してみてください
1、正例
- 主キー (id):
primary key
最初に数値型を使用int
し、tinyint
- 性別 (性別): 女性の場合は 0、男性の場合は 1; データベースにはブール型がないため、使用することを
mysql
お勧めしますtinyint
2.理由
- エンジンは、クエリと接続を処理するときに、文字列内の各文字を 1 つずつ比較するためです。
- デジタル タイプの場合、必要な比較は 1 回だけです。
- 文字はクエリと結合のパフォーマンスを低下させ、ストレージのオーバーヘッドを増加させます。
4 番目に、char の代わりに varchar を使用します。
1.反例
`address` char(100) DEFAULT NULL COMMENT '地址'
2、正例
`address` varchar(100) DEFAULT NULL COMMENT '地址'
3.理由
varchar
可変長フィールドは、データコンテンツの実際の長さに応じて格納され、ストレージスペースが小さいため、ストレージスペースを節約できます。char
宣言されたサイズに従って保存し、不十分な場合はスペースを埋めます。- 次に、クエリの場合、比較的小さなフィールドで検索する方が効率的です。
5. 技術拡張、char と varchar2 の違いは?
1.char
長さは固定ですがvarchar2
、長さは変更できます。
たとえば、文字列を格納すると、格納する文字“101”
はchar(10)
10 バイト (7 つのヌル文字を含む) を占め、データベースではスペースで占められ、同じvarchar2(10)
長さで 3 バイトしか占有されず、10 はちょうど最大値、10 文字未満を保存する場合は、実際の長さで保存します。
2.char
効率は よりわずかに高くなりvarchar2
ます。
3.いつchar
、いつ使用するのvarchar2
ですか?
char
とvarchar2
は相反する一体性の対であり、両者は補完的であり、効率比はスペースを節約するvarchar2
よりもわずかに悪くなります。効率を上げたい場合は、少しスペースを犠牲にしなければなりません。これは、データベース設計でよく言われることです。」スペースと交換する効率」。char
char
varchar2
スペースをchar
節約できますが、varchar2
列が頻繁に変更され、変更されたデータの長さが毎回異なる場合、これにより「行の移行」という現象が発生し、冗長な I/O が発生するため、データベース設計で回避する必要があります。 . 、この場合はchar
代わりに. フィールドに移動すると空白が自動的に埋められるため、空白も自動的に埋められますが、空白は削除されないため、 query と入力するときにそれらを使用することを忘れないでください。これがこの記事を書く理由です.varchar2
char
insert
char
select
char
trim
開発者がrpad()
トリックの使用を改良して、バインド変数をフィールドと比較できる型に変換する場合char
(もちろん、バインド変数を設定する方がtrim
、データベースの列を切り詰めるよりも優れています。関数を列に適用すると、trim
簡単に列の既存のインデックスを使用することはできません)、時間の経過に伴う列の長さの変化を考慮する必要がある場合があります。フィールドのサイズが変更されると、フィールド幅を変更する必要があるため、アプリは影響を受けます。
上記の理由により、固定幅のストレージ スペースによってテーブルや関連するインデックスが通常よりもはるかに大きくなり、バインド変数の問題が発生する可能性があるため、char 型はどのような場合でも避ける必要があります。
6. null の代わりにデフォルト値を使用します。
1.反例
SELECT * FROM user WHERE age IS NOT NULL
2、正例
SELECT * FROM user WHERE age>0
3.理由
- インデックスが使用されない、または
is null
使用されないという意味ではありませんが、これはバージョンとクエリのコストに関連しています。is not null
mysql
- インデックスを使用するコストが、インデックスを使用しないコストよりも高いことがわかった場合
mysql
、オプティマイザはインデックスを破棄します。これらの条件!=,<>,is null,is not null
は、多くの場合、インデックスを無効にするものと見なされます。 - 実際、一般にクエリのコストは高く、オプティマイザーは自動的にインデックスを破棄します。
- 値をデフォルト値に置き換える
null
と、インデックスに移動できることが多く、同時に意味が比較的明確になります。
7. where 句で != または <> 演算子を使用しない
1.反例
SELECT * FROM user WHERE salary!=5000
SELECT * FROM user WHERE salary<>5000
2.理由
- を使用する
!=
と<>
、インデックスが無効になる可能性があります where
句で!=
OR<>
演算子を使用しないようにしてください。そうしないと、エンジンがインデックスの使用を断念し、完全なテーブル スキャンを実行します。- ビジネスの優先順位を達成するには、本当に方法はありません。使用するしかありません。使用することは不可能ではありません。
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 table
where
句のないステートメントと機能的に同じdelete
です: どちらもテーブル内のすべての行を削除します。ただしtruncate table
、delete
より高速で、システムおよびトランザクション ログ リソースの使用量が少なくなります。
delete
このステートメントは、一度に 1 行ずつ削除し、削除された行ごとにトランザクション ログにエントリを記録します。truncate table
データは、テーブル データの格納に使用されたデータ ページを解放することによって削除され、ページの解放はトランザクション ログに記録されるだけです。
truncate table
テーブル内のすべての行を削除しますが、テーブル構造とその列、制約、インデックスなどは変更されません。新しい行の識別に使用されるカウント値は、この列のシードにリセットされます。ID カウント値を保持する場合は、代わりに DELETE を使用してください。テーブル定義とそのデータを削除する場合は、drop table
ステートメント。
foreign key
制約によって参照されるテーブルの場合truncate table
、where
句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 未満です。
- 関連付けられたテーブルの数が多いほど、コンパイル時間とオーバーヘッドが大きくなります
- 一時テーブルは毎回連想メモリに生成されます
- 接続テーブルは、より読みやすい小さな実行に分割する必要があります
- データを取得するために多くのテーブルを結合する必要がある場合、それは設計が悪いことを意味します
- アリの仕様では、複数のテーブルで 3 つ以下のテーブルをクエリすることが推奨されています。
2. インデックスは多すぎてはいけません。通常は 5 未満です。
- インデックスが多ければ多いほど、クエリの効率は向上しますが、挿入と更新の効率は低下します。
- インデックスは、データを格納できるテーブルとして理解でき、そのデータはスペースを占有します。
- インデックス テーブルのデータは並べ替えられますが、並べ替えには時間がかかります。
insert
データ量が膨大な場合、再構築によってレコードの順序が変更されるupdate
ため、特定の状況に応じて、インデックスの構築を慎重に検討する必要があります。- テーブル内のインデックスの数は 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 つだけあります。
- const: テーブルは最大で 1 行のデータと一致し、主キー クエリはより頻繁にトリガーされます。
- eq_ref: 前のテーブルの行の組み合わせごとに、このテーブルから行を読み取ります。const 型を除いて、これはおそらく最適な結合型です。
- ref: 前のテーブルの行の組み合わせごとに、一致するインデックス値を持つすべての行がこのテーブルから読み取られます。
- range: インデックスを使用して行を選択し、指定された範囲の行のみを取得します。=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN、または IN 演算子を使用してキーワード列を定数と比較する場合は、範囲を使用できます。
- index: この結合タイプは、索引ツリーのみがスキャンされることを除いて、ALL と同じです。通常、インデックス ファイルはデータ ファイルよりも小さいため、これは ALL よりも高速です。
- all: テーブル全体のスキャン。
- パフォーマンスのランキング: システム > const > eq_ref > ref > 範囲 > インデックス > すべて。
- 実際の 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
NULL
NULL
7. 疑似削除デザイン
8. データベースやテーブルの文字セットは可能な限りUTF8を使用する
(1) 文字化けの問題を回避できる。
(2) 異なる文字セットの比較と変換によるインデックスの無効化の問題を回避できます。
9、表からcount(*)を選択;
このような無条件のカウントは、完全なテーブル スキャンを引き起こし、ビジネス上の意味がないため、避ける必要があります。
10.フィールドでの式操作を避ける
(1) SQL 解析中に、フィールドが式に関連している場合、完全なテーブル スキャンが実行されます
(2) フィールドはクリーンで式がなく、インデックスが有効になります
11. 一時テーブルについて
(1) システム テーブル リソースの消費を減らすために、一時テーブルの頻繁な作成と削除を避ける
(2) 新しい一時テーブルを作成するときに、一度に大量のデータが挿入される場合は、create の代わりに select into を使用できます大量のログが発生しないようにするためのテーブル ;
(3) データ量が多くない場合は、システム テーブルのリソースを軽減するために、最初にテーブルを作成してから挿入する必要があります;
(4) 使用する場合ストアド プロシージャの最後ですべての一時テーブルを明示的に削除してください。最初にテーブルを切り捨て、次にテーブルを削除します。これにより、システム テーブルの長期的なロックを回避できます。
12. インデックスは、性別など、大量の繰り返しデータを含むフィールドには適していないため、フィールドを並べ替えるためにインデックスを作成する必要があります
13. 重複排除の個別フィルター フィールドが少ない
- 明確なステートメントは、
cpu
ないステートメントよりも時間がかかりますdistinct
- 多くのフィールドをクエリする場合、使用されている場合
distinct
、データベース エンジンはデータを比較し、重複データを除外します。 cpu
ただし、この比較とフィルタリングのプロセスは、時間などのシステム リソースを消費します。
14. 大規模なトランザクション操作を回避し、システムの同時実行機能を改善するようにしてください
15. すべてのテーブルはInnodb
ストレージ エンジンを使用する必要があります
Innodb
「トランザクションをサポートし、行レベルのロックをサポートし、回復性を向上させる」と、高い並行性の下でパフォーマンスが向上するため、特別な要件 (つまりInnodb
、列のストレージ、ストレージ スペースのデータなど、満たすことができない機能) がなければ、パフォーマンスは向上します。など)、すべてのテーブルはInnodb
ストレージ エンジンを使用する必要があります。
16. カーソルの使用を避ける
カーソルの効率が悪いため、カーソルで操作するデータが10,000行を超える場合は、書き換えを検討する必要があります。
二十一、マインドマップ
「MySql Database Advanced Practice」を5部送付
より質の高い記事: Nezha Essence 記事の概要