あなたの質問に対処するのは、「JOIN DECOMPOSITION」という主題です。
本の209ページによると
マルチテーブル結合の代わりに複数のシングルテーブルクエリを実行し、アプリケーションで結合を実行することにより、結合を分解できます。たとえば、この単一のクエリの代わりに:
SELECT * FROM tag
JOIN tag_post ON tag_post.tag_id = tag.id
JOIN post ON tag_post.post_id = post.id
WHERE tag.tag = 'mysql';
次のクエリを実行できます。
SELECT * FROM tag WHERE tag = 'mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);
一体どうしてこんなことをするの?何も見返りなくクエリの数を増やしたため、一見無駄に見えます。ただし、このような再構築により、実際にパフォーマンスが大幅に向上します。
- キャッシングはより効率的です。多くのアプリケーションは、テーブルに直接マップする「オブジェクト」をキャッシュします。この例では、タグを持つオブジェクト
mysql
が既にキャッシュされている場合、アプリケーションは最初のクエリをスキップします。キャッシュでIDが123、567、または908の投稿を見つけた場合は、IN()
リストから削除できます。クエリキャッシュもこの戦略の恩恵を受ける可能性があります。1つのテーブルのみが頻繁に変更される場合、結合を分解するとキャッシュの無効化の数を減らすことができます。
- クエリを個別に実行すると、ロックの競合を減らすことができる場合があります
- アプリケーションで結合を行うと、異なるサーバーにテーブルを配置することでデータベースを簡単に拡張できます。
- クエリ自体はより効率的です。この例で
IN()
は、結合の代わりにリストを使用すると、MySQLが行IDをソートし、結合で可能な場合よりも最適に行を取得できます。
- 冗長な行アクセスを減らすことができます。アプリケーションで結合を行うことは、各行を1回だけ取得することを意味します。一方、クエリでの結合は、基本的に同じデータに繰り返しアクセスする可能性がある非正規化です。同じ理由で、このような再構築により、ネットワークトラフィック全体とメモリ使用量も削減される可能性があります。
- ある程度まで、この手法は、MySQLが結合を実行するために使用するネストされたループアルゴリズムの代わりに、ハッシュ結合を手動で実装すると見なすことができます。ハッシュ結合の方が効率的かもしれません。
その結果、以前のクエリから大量のデータをキャッシュして再利用したり、複数のサーバーにデータを分散しIN()
たり、結合をリストに置き換えたり、結合が同じテーブルを複数回参照したりすると、アプリケーションでの結合の実行がより効率的になります。
観察
InnoDBはクエリキャッシュをクロスチェックするときに少し手間がかかるため、最初の箇条書きが気に入っています。
最後の箇条書きについては、ネストループアルゴリズムを説明する投稿を2013年3月11日に投稿しました(JOIN条件とWHERE条件の実行に違いはありますか?)。これを読んだ後、結合分解がどれほど優れているかがわかります。
この本の他のすべての点に関しては、開発者は最終結果としてパフォーマンスを本当に探しています。高速ディスクの使用、CPU /コアの追加、ストレージエンジンの調整、構成ファイルの調整など、パフォーマンスの向上を外部の手段(アプリケーションの外部)に依存しているものもあります。他の人は座屈してより良いコードを書くでしょう。ストアドプロシージャですべてのビジネスインテリジェンスをコーディングすることに頼る人もいるかもしれませんが、それでも結合分解は適用しません(データベースレイヤーにアプリケーションロジックを配置することに対する、または他の投稿と一緒の議論を参照)。それはすべて、各デベロッパーショップの文化と寛容次第です。
一部のユーザーはパフォーマンスに満足しており、コードに触れない場合があります。他の人は、彼らが作曲に参加しようとする場合に得ることができる大きな利点があることに単に気づかない。
喜んでいる開発者のために...
試してみる !!!