この記事では、MySQLの使用に関する実用的なヒントを提供したいと思います。
すぐに予約する:
- この記事はMySQLについて書かれていますが、一般的なことはすべてのDBMSに当てはまる可能性があります。
- 記事に書かれていることはすべて私の個人的な観点であり、究極の真実ではありません。
- アドバイスは新しいもののふりをするものではなく、読んだ文献や個人的な経験を一般化した結果です。
- この記事では、MySQLの構成の問題には触れません。
MySQLを使用する際の問題は、次の3つのグループに分けられます(重要度の高い順に)。
- インデックスの使用または誤用。
- 無効なデータベース構造。
- 誤った\最適でないSQLクエリ。
これらの各グループについて詳しく見ていきましょう。
インデックスを使用します。
インデックスを使用または誤用しないことは、ほとんどの場合クエリを遅くします。 インデックスの操作メカニズムに詳しくない、またはマニュアルでまだ読んでいない人のために、それを読むことを強くお勧めします。
インデックスを使用するためのヒント:
- すべてをインデックス化する必要はありません。 多くの場合、意味を理解せずに、人々は単にテーブルのすべてのフィールドにインデックスを付けます。 インデックスは選択を高速化しますが、行の挿入と更新を遅くするので、各インデックスを選択することには意味があります。
- インデックスを特徴付ける主なパラメータの1つは選択性です。インデックスのさまざまな要素の数です。 2つまたは3つの可能な値があるフィールドにインデックスを付けることは意味がありません。 このようなインデックスのメリットはほとんどありません。
- インデックスの選択は、このテーブルに対するすべてのクエリの分析から始める必要があります。 非常に多くの場合、このような分析の後、3つまたは4つのインデックスの代わりに、1つのコンポジットを作成できます。
- 複合インデックスを使用する場合、インデックス内のフィールドの順序が重要です。
- インデックスをカバーすることを忘れないでください。 クエリ内のすべてのデータがインデックスから取得できる場合、MySQLはテーブルに直接アクセスしません。 このような要求は非常に迅速に実行されます。 たとえば、SELECT name FROM user WHERE login =“ test”を照会するために、インデックス(ログイン、名前)がある場合、テーブルにアクセスする必要はありません。 複合インデックスにフィールドを追加すると、インデックスがカバーされ、クエリが高速化される場合があります。
- 行インデックスの場合、多くの場合、行の一部のみにインデックスを付けるだけで十分です。 これにより、インデックスのサイズを大幅に削減できます。
- %がLIKE(SELECT * FROMテーブルWHEREフィールドLIKE '%test')の先頭にある場合、インデックスは使用されません。
- FULLTEXTインデックスは、MATCH ... AGAINST構文でのみ使用されます。
DB構造
適切に設計されたデータベースは、データベースを迅速かつ効果的に使用するための鍵です。 一方、不十分に設計されたデータベースは常に開発者にとって頭痛の種です。
データベース設計のヒント:
- 可能な限り小さいデータ型を使用してください。 データ型が大きいほど、テーブルが大きいほど、データを取得するためにより多くのディスクアクセスが必要になります。 非常に便利な手順を使用します。SELECT * FROM table_name PROCEDURE ANALYZE(); 可能な最小データ型を決定します。
- 設計段階では、通常のフォームに従ってください。 多くの場合、プログラマーはこの段階で非正規化に頼ります。 ただし、ほとんどの場合、プロジェクトの開始時に、これがどのように発生するかは明らかではありません。 テーブルの非正規化は、次善の非正規化テーブルに悩むよりもはるかに簡単です。 はい。JOINは、誤って非正規化されたテーブルよりも高速に動作する場合があります。
- 意図的に必要としない限り、NULL列を使用しないでください。
- ループ内のクエリを避けます。 SQLはセットの言語であり、関数の言語ではなくセットの言語でクエリ作成に取り組む必要があります。
- クエリでは*(アスタリスク)を避けてください。 怠けすぎて、選択したフィールドを正確にリストしないでください。 これにより、フェッチおよび送信されるデータの量が削減されます。 さらに、インデックスをカバーすることを忘れないでください。 テーブル内のすべてのフィールドを実際に選択した場合でも、それらをリストする方が適切です。 まず、コードの可読性が向上します。 星を使用する場合、テーブルを調べずにテーブル内のフィールドを見つけることはできません。 次に、今日のテーブルには5つのINT列があり、1か月後に別のTEXTおよびBLOBが追加され、アスタリスクが残り、残りました。
- ページ分割するときは、SQL_CALC_FOUND_ROWSおよびSELECT FOUND_ROWS()を使用してレコードの総数を取得します。 SQL_CALC_FOUND_ROWSを使用する場合、MySQLは選択された行数をキャッシュし(LIMITを適用する前)、SELECT FOUND_ROWS()はクエリを再度実行せずにこのキャッシュされた値のみを返します。
- INSERTには複数の挿入構文があることに注意してください。 1つのクエリは、ループ内の多くのクエリよりも1桁高速に実行されます。
- すべてのデータが必要でない場合は、LIMITを使用します。
- INSERT ... ON DUPLICATE KEY UPDATE ...をフェッチの代わりに使用し、その後にINSERTまたはUPDATEを使用します。多くの場合、REPLACEの代わりに使用します。
- 素晴らしいGROUP_CONCAT関数を忘れないでください。 彼女は複雑なリクエストに対応できます。