12

漏れやすい抽象化に関するJoel Spolsky の 記事から:

[C]特定の SQL クエリは、他の論理的に同等のクエリよりも何千倍も遅くなります。これの有名な例は、結果セットが同じです。

これの詳細わかる人いますか?

4

3 に答える 3

27

明らかに、 a = b および b = c => a = c - これは推移閉包に関連しています。Joel が指摘していたのは、一部の SQL サーバーはクエリの最適化が苦手なため、SQL クエリの一部は例のように「余分な」修飾子を付けて記述される可能性があるということです。

この例では、上記の a、b、および c はしばしば異なるテーブルを参照し、a=b のような操作は結合として実行されることに注意してください。テーブル a のエントリ数が 1000、b が 500、c が 20 であるとします。次に、a と b の結合には 1000x500 行の比較が必要です (これは私のばかげた例です。実際には、複雑さを軽減するより優れた結合アルゴリズムが存在する可能性があります)。 b,c には 500x20 の比較が必要です。最適化コンパイラは、最初に b,c の結合を実行し、次に結果を a = b で結合する必要があると判断します。これは、b=c で期待される行が少ないためです。(b=c) と (a=b) の合計で、それぞれ約 500x20 + 500x1000 の比較があります。その後、返された行の間で交差を計算する必要があります(結合を介しても推測しますが、わかりません)。

Sql サーバーが、これが a = c を意味することも推論する論理推論モジュールを持つことができるとします。次に、おそらく b,c の結合を実行し、次に a,c の結合を実行します (これも仮定のケースです)。これには、500x20 + 1000x20 の比較と、その後の交差計算が必要になります。予想される #(a=c) が小さい場合 (ある程度のドメイン知識があるため)、2 番目のクエリははるかに高速になります。

全体的に私の回答は長くなりすぎましたが、これは SQL クエリの最適化が簡単な作業ではないことを意味します。そのため、一部の SQL サーバーはうまく機能しない可能性があります。

詳細については、http://en.wikipedia.org/wiki/Query_optimizerを参照するか、これを読んでいるデータベースを期待してください。

しかし、哲学的に言えば、(抽象化としての) SQL は、実装のすべての側面を隠すことを意図していました。これは宣言型であることを意図していました (SQL サーバー自体が SQL クエリの最適化手法を使用して、クエリをより効率的にするために言い換えることができます)。しかし、現実の世界ではそうではありません。多くの場合、データベース クエリを人間が書き直して、より効率的にする必要があります。

全体として、この記事の要点は、抽象化は非常に優れたものであり、完璧な抽象化は存在しないということです。

于 2008-12-29T03:59:33.280 に答える
18

すべてが 1 つのテーブルにまとめられている簡単な説明を次に示します。

A と C は両方とも索引付けされているが、B は索引付けされていないとします。オプティマイザが A = C であることを認識できない場合、両方の WHERE 条件にインデックスなしの B を使用する必要があります。

しかし、次にサーバーに a=c を伝えると、最初にそのフィルターを効率的に適用し、ワーキング セットのサイズを大幅に削減できます。

于 2008-12-29T15:21:59.267 に答える
1

ここでは「ある」という言葉が有効な用語だと思います。オプティマイザが a=c であることを本当に理解するには、a の等価性を解析し、推移的な関係で "c" に接続して関係を推測する必要があります。

将来的には、SQL オプティマイザーがこれを賢くする可能性があると思います (まだそうでない場合)。

于 2008-12-29T03:56:55.047 に答える