私は最近、JOIN(SQL)は役に立たないと主張した別の開発者と話し合いました。これは技術的には真実ですが、ジョインを使用すると、コード(C#またはJava)で複数のリクエストとリンクテーブルを作成するよりも効率が悪いと付け加えました。
彼にとっての参加は、パフォーマンスを気にしない怠惰な人々のためのものです。これは本当ですか?結合の使用を避けるべきですか?
私は最近、JOIN(SQL)は役に立たないと主張した別の開発者と話し合いました。これは技術的には真実ですが、ジョインを使用すると、コード(C#またはJava)で複数のリクエストとリンクテーブルを作成するよりも効率が悪いと付け加えました。
彼にとっての参加は、パフォーマンスを気にしない怠惰な人々のためのものです。これは本当ですか?結合の使用を避けるべきですか?
回答:
いいえ、そのような信じられないほど間違った意見を抱いている開発者は避けるべきです。
多くの場合、データベースの結合は、DBのラウンドトリップを回避し、DBがインデックスを使用して結合を実行できるため、クライアントを介して行うものよりも数桁高速です。
私の頭の外では、正しく使用された結合が同等のクライアント側の操作よりも遅い単一のシナリオを想像することさえできません。
編集:カスタムクライアントコードが単純なDB結合よりも効率的に処理できるまれなケースがあります(メリトンによるコメントを参照)。しかし、これは非常に例外です。
あなたの同僚は、SQLなしのドキュメントデータベースまたはキー値ストアでうまくいくように思えます。それ自体が非常に優れたツールであり、多くの問題に適しています。
ただし、リレーショナルデータベースは、セットを操作するために大幅に最適化されています。多くのラウンドトリップよりもはるかに効率的な結合に基づいてデータをクエリする方法は数多くあります。これが、rdbmsの多様性の源です。nosqlストアでも同じことを実現できますが、多くの場合、クエリの異なる性質ごとに適した個別の構造を構築することになります。
要するに:私は同意しません。RDBMSでは、結合が基本です。それらを使用していない場合は、RDBMSとして使用していません。
まあ、彼は一般的なケースでは間違っています。
データベースは、オプティマイザヒント、テーブルインデックス、外部キーの関係、および場合によっては他のデータベースベンダー固有の情報を利用して、さまざまな方法で最適化できます。
いいえ、できません。
データベースは特にデータのセットを操作するように設計されています(明らかに...)。したがって、これは非常に効率的です。自分のコードで本質的に手動の結合を行うことにより、彼はその仕事のために特別に設計されたものの役割を引き継ぐことを試みています。彼のコードがデータベースのコードと同じくらい効率的である可能性は非常に低いです。
余談ですが、結合なしで、データベースを使用するポイントは何ですか?彼はテキストファイルを使用することもできます。
「怠惰」が少ないコードを記述したい人々として定義されている場合、私は同意する。「怠惰」が、自分の得意なことをツールに実行してもらいたい人々として定義されている場合、私は同意する。したがって、もし彼が(良いプログラマーの属性に関して)ラリー・ウォールに単に同意しているなら、私は彼に同意します。
はい、そうすべきです。
また、パフォーマンスのため、C#ではなくC ++を使用する必要があります。C#は怠惰な人向けです。
ダメダメダメ。パフォーマンス上の理由から、C ++ではなくCを使用する必要があります。C ++は怠惰な人向けです。
ダメダメダメ。パフォーマンスのため、Cの代わりにアセンブリを使用する必要があります。Cは怠惰な人向けです。
はい、冗談です。結合なしでより高速なプログラムを作成でき、結合なしでより少ないメモリを使用してプログラムを作成できます。しかし、多くの場合、開発時間はCPU時間とメモリよりも重要です。少しパフォーマンスをあきらめて、あなたの人生を楽しんでください。小さなパフォーマンスのために時間を無駄にしないでください。そして、彼に「あなたの場所からあなたのオフィスまでまっすぐな高速道路を作ってみませんか?」
「これは技術的に正しい」-同様に、SQLデータベースは役に立たない:一連のCSVファイルを使用して同じ結果を得ることができ、それらをコードで相互に関連付けることができる場合に、SQLデータベースを使用する意味は何ですか?抽象化は怠惰な人々のためのものです。ハードウェア上でマシンコードのプログラミングに戻りましょう。;)
また、彼の主張は、最も複雑な場合を除いてすべて正しくありません。RDBMSは、JOINを高速化するために大幅に最適化されています。リレーショナルデータベース管理システムですね。
unnecessary
なく語句に使用していた場合により効果的useless
でした。ジョインが役に立たないと言うことは、技術的な考慮を必要としないため、明らかに真実ではありません。いずれにせよ、OPのとのRDBMSのポイントの同僚の誤解はsandly珍しいことではありません。stackoverflow.com/q/5575682/47550
私が最後に働いた会社もSQL結合を使用していませんでした。代わりに、この作業を水平方向にスケーリングするように設計されたアプリケーションレイヤーに移動しました。この設計の根拠は、データベース層での作業を回避することです。通常、ボトルネックになるのはデータベースです。データベースよりもアプリケーション層の複製が簡単です。他の理由が考えられます。しかし、これは私が今思い出すことができるものです。
はい、アプリケーション層で行われる結合は、データベースで行われる結合と比較して非効率的であることに同意します。より多くのネットワーク通信も。
SQL結合を回避することについて、私は固い立場に立っていないことに注意してください。
例を考えてみましょう:請求書レコードを含むテーブルと、請求書項目レコードを含む関連テーブル。クライアントの疑似コードを考えてみましょう:
for each (invoice in invoices)
let invoiceLines = FindLinesFor(invoice)
...
それぞれ10行の100,000の請求書がある場合、このコードは100万のテーブルから10の請求書行を検索し、100,000回実行します。テーブルサイズが大きくなると、選択操作の数が増加し、各選択操作のコストが増加します。
コンピュータが高速であるため、数千レコード以下の場合、2つのアプローチのパフォーマンスの違いに気付かない場合があります。コストの増加は線形を超えるため、レコード数が(たとえば、数百万に)増加すると、違いに気付き始め、データセットのサイズが大きくなるにつれて違いが許容できなくなります。
ただし、結合。テーブルのインデックスを使用し、2つのデータセットをマージします。これは、ランダムにN回アクセスするのではなく、2番目のテーブルを効果的に1回スキャンすることを意味します。外部キーが定義されている場合、データベースには、内部に保存されている関連レコード間のリンクがすでにあります。
これを自分で行うことを想像してみてください。生徒のアルファベット順のリストとすべての生徒の成績レポートが記載されたノート(クラスごとに1ページ)があります。ノートブックは、リストと同じ順序で、生徒の名前順にソートされています。どのように進めますか?
または:
彼は間違いなく間違っている。C#やJavaなどの言語内でのデータ操作には明確な長所がありますが、SQL自体の性質により、結合はデータベースで最も高速です。
SQLはデータに関する詳細な統計を保持し、インデックスを正しく作成した場合、数百万のレコードを非常にすばやく見つけることができます。データベースレベルで結合を実行できるのに、なぜすべてのデータをC#にドラッグして結合を実行するのでしょうか。
反復的に何かを行う必要がある場合は、C#を使用するプロが関与します。行ごとに関数を実行する必要がある場合は、C#内で実行する方が高速です。そうでない場合、データの結合はDBで最適化されます。
私は彼がデータベースが何のために使われるべきかについて限られた見解を持っているのではないかと思います。パフォーマンスを最大化する1つの方法は、データベース全体をメモリに読み込むことです。この状況では、パフォーマンスが向上する可能性があり、メモリを効率化するために結合を実行したい場合があります。ただし、これは実際にはデータベースのIMHOとしてデータベースを使用しているわけではありません。
MEMORY
エンジン)を作成できます。データベースなしでデータベース機能を再実装することは、通常、NIHの深刻なケースの兆候です;)
いいえ、その場限りのC#/ Javaのデータベースコードで結合が最適化されているだけではありません。しかし、通常はいくつかのフィルタリング手法を適用でき、さらに優れたパフォーマンスが得られます。
彼は間違っています、結合は有能なプログラマが使用するものです。彼の提案した方法がより効率的であるいくつかの限られたケースがあるかもしれません(そして、私はおそらくDocumantデータベースを使用しているでしょう)ですが、あなたが何らかの適切な量のデータを持っているなら、私はそれを見ることができません。たとえば、次のクエリを見てください。
select t1.field1
from table1 t1
join table2 t2
on t1.id = t2.id
where t1.field2 = 'test'
table1に1000万レコード、table2に100万レコードあるとします。表1の900万件のレコードがwhere句に一致するとします。それらのうち15個だけがtable2にもあると想定します。このsqlステートメントを実行できます。このSQLステートメントは、適切にインデックスが作成されるとミリ秒かかり、1列のデータのみでネットワーク全体に15レコードを返します。または、2列のデータを含む1000万レコードを送信し、1列のデータを含む別の100万レコードをネットワーク経由で個別に送信し、それらをWebサーバーで結合することができます。
またはもちろん、常に大量のデータと継続的に変化するデータがある場合、データベースのコンテンツ全体を常にWebサーバーに保持することもできます。リレーショナルデータベースの品質が必要ない場合は、使用しないでください。ただし、使用する場合は、正しく使用してください。
この議論は、ソフトウェア開発者としてのキャリアの中でよく耳にしました。それが述べられているほとんどいつも、主張をしている人はリレーショナルデータベースシステム、それらがどのように機能するか、そしてそのようなシステムがどう使われるべきであるかについてあまり知識を持っていませんでした。
はい、正しく使用しないと、結合は役に立たないか、さらには危険であるように見えます。しかし、正しい方法で使用すると、データベース実装が最適化を実行し、開発者が正しい結果を最も効率的に取得するのを「助ける」ための多くの可能性があります。
JOIN
データベースを使用して、データの各部分が相互に関連していると予想される方法をデータベースに通知することを忘れないでください。したがって、データベースに、実行しようとしていることに関するより多くの情報を提供し、必要に応じてデータベースを適合させることができます。
だから答えは間違いなく:いいえ、JOINS
まったく役に立たない!
私が真剣に誤解していない限り、質問のロジックには非常に欠陥があります
AごとにBに20行ある場合、Aの1000行はBに20k行を意味します。マッピングを含む20k行の多対多テーブル "AB"がない限り、Bに100行はあり得ません。 。
そのため、100行のB行のうち20行が各A行にマップされるすべての情報を取得するには、ABもテーブル化します。したがって、これは次のいずれかになります。
したがって、クライアントの "JOIN"は、データを調べるときに値を追加しません。それは悪い考えではありません。データベースから1つのオブジェクトを取得する場合は、オブジェクトを個別の結果セットに分割する方が理にかなっています。レポートタイプの呼び出しの場合は、ほぼ常に1つにまとめます。
いずれにせよ、この規模のクロスジョインはほとんど役に立ちません。それは悪い例です。
あなたはどこかに参加する必要があり、それがRDBMSが得意なことです。私は、もっと上手くできると思っているクライアントコードモンキーとは協力したくありません。
結果論:
クライアントに参加するには、DataTables(.net内)などの永続オブジェクトが必要です。フラット化された結果セットが1つある場合は、DataReaderなどの軽量なものを介して消費できます。大量=データベースのJOINを回避するために使用される大量のクライアントリソース。