sql >> データベース >  >> RDS >> Mysql

データベース内のクエリを最適化する方法-基本

    すべてのwhere条件とすべてのjoin...on条件を検索する必要があります。 2つは同じように機能します。

    書くとしましょう

    select name
    from customer
    where customerid=37;
    

    どういうわけか、DBMSはcustomerid=37の1つまたは複数のレコードを検索する必要があります。インデックスがない場合、これを行う唯一の方法は、customeridを37と比較するテーブル内のすべてのレコードを読み取ることです。インデックスが見つかったとしても、インデックスが1つしかないことを知る方法がないため、探し続ける必要があります。その他。

    customeridにインデックスを作成する場合、DBMSにはインデックスを非常に迅速に検索する方法があります。これは順次検索ではありませんが、データベースに応じて、バイナリ検索またはその他の効率的な方法です。正確にどのように問題ではないので、シーケンシャルよりもはるかに高速であることを受け入れてください。次に、インデックスはそれを適切な1つまたは複数のレコードに直接移動します。さらに、インデックスが「一意」であると指定すると、データベースは1つしか存在できないことを認識しているため、1秒を探すのに時間を無駄にすることはありません。 (そして、DBMSはあなたが秒を追加することを防ぎます。)

    ここで、このクエリについて考えてみましょう。

    select name
    from customer
    where city='Albany' and state='NY';
    

    これで2つの条件があります。これらのフィールドの1つだけにインデックスがある場合、DBMSはそのインデックスを使用してレコードのサブセットを検索し、それらを順番に検索します。たとえば、州のインデックスがある場合、DBMSはNYの最初のレコードをすばやく検索し、city ='Albany'を順番に検索して、NYの最後のレコードに到達すると検索を停止します。

    両方のフィールドを含むインデックスがある場合、つまり「顧客(州、市)にインデックスを作成する」の場合、DBMSはすぐに適切なレコードにズームできます。

    各フィールドに1つずつ、合計2つの個別のインデックスがある場合、DBMSには、使用するインデックスを決定するために適用されるさまざまなルールがあります。繰り返しになりますが、これがどのように行われるかは、使用している特定のDBMSによって異なりますが、基本的には、レコードの総数、異なる値の数、および値の分布に関する統計を保持しようとします。次に、それらのレコードを順番に検索して、他の条件を満たすレコードを探します。この場合、DBMSは、州よりもはるかに多くの都市があることを認識している可能性があります。そのため、都市インデックスを使用することで、「アルバニー」レコードにすばやくズームできます。次に、これらを順番に検索し、それぞれの状態を「NY」と照合します。カリフォルニア州アルバニーの記録がある場合、これらはスキップされます。

    すべての参加には、なんらかのルックアップが必要です。

    私たちが書くと言う

    select customer.name
    from transaction
    join customer on transaction.customerid=customer.customerid
    where transaction.transactiondate='2010-07-04' and customer.type='Q';
    

    ここで、DBMSは最初に読み取るテーブルを決定し、そこから適切なレコードを選択してから、他のテーブルで一致するレコードを見つける必要があります。

    transaction.transactiondateとcustomer.customeridにインデックスがある場合、最善の計画は、この日付のすべてのトランザクションを検索し、それぞれについて、一致するcustomeridを持つ顧客を検索し、顧客が適切なタイプ。

    customer.customeridにインデックスがない場合、DBMSはトランザクションをすばやく見つけることができますが、トランザクションごとに、一致する顧客IDを探すために顧客テーブルを順番に検索する必要があります。 (これはおそらく非常に遅いでしょう。)

    代わりに、transaction.customeridとcustomer.typeにある唯一のインデックスがあるとします。その場合、DBMSは完全に異なる計画を使用する可能性があります。おそらく、正しいタイプのすべての顧客について顧客テーブルをスキャンし、次にこれらのそれぞれについて、この顧客のすべてのトランザクションを検索し、適切な日付を順番に検索します。

    最適化の最も重要な鍵は、どのインデックスが実際に役立つかを把握し、それらのインデックスを作成することです。余分な未使用のインデックスは、それらを維持するための作業が必要であり、一度も使用されない場合、これは無駄な労力であるため、データベースに負担をかけます。

    EXPLAINコマンドを使用すると、DBMSが特定のクエリに使用するインデックスを確認できます。これを常に使用して、クエリが適切に最適化されているかどうか、または追加のインデックスを作成する必要があるかどうかを判断します。 (出力の説明については、このコマンドのドキュメントをお読みください。)

    警告:DBMSは、各テーブルのレコード数やさまざまな値の数などの統計を保持していると言ったことを思い出してください。 EXPLAINは、データが変更された場合、昨日とはまったく異なる計画を今日提供する可能性があります。たとえば、2つのテーブルを結合するクエリがあり、これらのテーブルの1つが非常に小さく、もう1つが大きい場合、最初に小さいテーブルを読み取り、次に大きいテーブルで一致するレコードを見つけることに偏ります。テーブルにレコードを追加すると、どちらが大きくなるかが変わる可能性があるため、DBMSはその計画を変更することになります。したがって、現実的なデータを含むデータベースに対してEXPLAINSを実行するようにしてください。各テーブルに5つのレコードがあるテストデータベースに対して実行することは、ライブデータベースに対して実行するよりもはるかに価値がありません。

    まあ、言うことができることはもっとたくさんありますが、私はここで本を書きたくありません。



    1. MYSQL左結合NULL値を選択するにはどうすればよいですか?

    2. JPA/HibernateはOrderというエンティティを作成できません

    3. LaravelとMySQLを使用して巨大なレコードを取得するにはどうすればよいですか?

    4. ユーザー登録時にサブドメインを自動作成すると、新しいWebサイトが作成されますか、それともWebサイトの外観が表示されますか?