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

JOIN関数を使用する必要がありますか、それともループ構造で複数のクエリを実行する必要がありますか?

    提案された2つのソリューションはどちらもおそらく最適ではありませんが、ソリューション1は予測不可能であるため、本質的に欠陥があります!

    大規模なデータベースを扱うときに最初に学ぶことの1つは、クエリを実行するための「最良の方法」は、データベース内の要因(メタデータと呼ばれる)に依存することが多いということです。

    • 行数。
    • クエリしているテーブルの数。
    • 各行のサイズ。

    このため、問題に対する特効薬の解決策はありそうにありません。あなたのデータベースは私のデータベースと同じではありません。最高のパフォーマンスが必要な場合は、さまざまな最適化のベンチマークを行う必要があります。

    正しいインデックスの適用と構築 (そしてMySQLでのインデックスのネイティブ実装を理解することで)データベースでより多くのことができます。

    めったに破られるべきではないクエリに関するいくつかの黄金のルールがあります:

    • ループ構造で実行しないでください 。よくあることですが、接続の作成、クエリの実行、応答の取得にかかるオーバーヘッドは高くなります。
    • SELECT *は避けてください 必要な場合を除いて 。より多くの列を選択すると、SQL操作のオーバーヘッドが大幅に増加します。
    • インデックスを知るEXPLAINを使用する 使用されているインデックスを確認し、使用可能なものを使用するようにクエリを最適化し、新しいインデックスを作成できるようにする機能。

    このため、2つのうち、2番目のクエリに進みます(SELECT *を置き換えます) 必要な列のみ)、しかし 最適化する時間があれば、クエリを構造化するためのより良い方法がおそらくあります。

    ただし、速度はすべきではありません これに関する唯一の考慮事項は、提案1を使用しない大きな理由です:

    予測可能性:読み取りロックが優れている理由

    他の回答の1つは、テーブルを長期間ロックすることは悪いことであり、したがって複数クエリソリューションが優れていることを示唆しています。

    これは真実から遠く離れることはできません 。実際、多くの場合、単一のロッキングSELECTを実行することの予測可能性について議論します。 クエリは、最適化と速度のメリットよりも、そのクエリを実行するための大きな議論です。

    まず、SELECTを実行すると MyISAMまたはInnoDBデータベース(MySQLのデフォルトシステム)での(読み取り専用)クエリでは、テーブルが読み取りロックされます。これにより、読み取りロックが解除されるまで(SELECTのいずれか)、テーブルでWRITE操作が発生するのを防ぎます。 クエリが完了するか失敗します)。その他のSELECT クエリは影響を受けないため、マルチスレッドアプリケーションを実行している場合は、引き続き機能します。

    この遅延は良いことです。 なぜ、あなたは尋ねるかもしれませんか?リレーショナルデータの整合性。

    例を見てみましょう。ゲームの多数のユーザーのインベントリに現在あるアイテムのリストを取得する操作を実行しているので、この参加を行います:

    SELECT * FROM `users` JOIN `items` ON `users`.`id`=`items`.`inventory_id` WHERE `users`.`logged_in` = 1;
    

    このクエリ操作中に、ユーザーがアイテムを別のユーザーに交換するとどうなりますか?このクエリを使用すると、クエリを開始したときのゲームの状態がわかります。アイテムは、クエリを実行する前に持っていたユーザーのインベントリに1回存在します。

    しかし、ループで実行するとどうなりますか?

    ユーザーが詳細を読む前と後のどちらで取引したか、および2人のプレーヤーの在庫を読み取る順序に応じて、次の4つの可能性があります。

    1. アイテムは最初のユーザーの在庫に表示される可能性があります(スキャンユーザーB->スキャンユーザーA->アイテム取引またはスキャンユーザーB->スキャンユーザーA->アイテム取引)
    2. アイテムは2番目のユーザーの在庫に表示される可能性があります(取引されたアイテム->ユーザーAをスキャン->ユーザーBをスキャンまたは取引されたアイテム->ユーザーBをスキャン->ユーザーAをスキャン)
    3. アイテムは両方に表示される可能性があります 在庫(ユーザーAをスキャン->取引されたアイテム->ユーザーBをスキャン)
    4. アイテムはどちらにも表示されない ユーザーの在庫の内訳(ユーザーBをスキャン->取引されたアイテム->ユーザーAをスキャン)

    これが意味するのは、クエリの結果を予測したり、関係の整合性を確保したりすることができないということです。 。

    火曜日の深夜にアイテムID1000000の男に$5,000を渡すことを計画している場合は、$10,000が手元にあることを願っています。プログラムがスナップショットの作成時に一意である一意のアイテムに依存している場合、この種のクエリで例外が発生する可能性があります。

    ロックは予測可能性を向上させるので優れています 整合性を保護します 結果の。

    注:トランザクションを使用して、ループを強制的にロックすることができます。 、ただし、それでも 遅くなります。

    ああ、そして最後に、プリペアドステートメントを使用してください!

    絶対にすべきではありません 次のようなステートメントがあります:

    mysqli_query("SELECT * FROM Table2 WHERE ColumnAId=" . $row['ColumnAId'], $con);
    

    mysqli プリペアドステートメントのサポート 。それらについて読んで使用すると、データベースに何かひどいことが起こるのを防ぐのに役立ちます 。



    1. DriverManager適切なドライバーがありませんmysql

    2. Symfony3-SQLSTATE[HY000][2002]そのようなファイルまたはディレクトリはありません

    3. SQLServerインスタンスのすべてのデータベースで主キー制約のないテーブルのリストを取得する方法-SQLServer/TSQLチュートリアルパート62

    4. MySQLでトリガーを無効にする方法は?