18

私は学校でデータベースコースに参加しています。先生は私たちに簡単な演習を与えました: 次の簡単なスキーマを考えてみましょう:

Table Book:
    Column title (primary key)
    Column genre (one of: "romance", "polar", ...)

Table Author:
    Column title (foreign key on Book.title)
    Column name
    Primary key on (title, name)

質問の中に次のようなものがありました。

ロマンスの本を書いた著者を返すクエリを作成します。

私はこの答えを提案しました:

select distinct name 
from Author where title in (select title from Book where genre = "romance")

しかし、先生はそれは間違っていて、正解は次のとおりだと言いました。

select distinct name 
from Book, Author 
where Book.title = Author.title 
  and genre = "romance"

私が説明を求めたとき、私が得たのは「コースにもっと注意を払っていれば、その理由がわかるだろう」ということだけでした。素晴らしい。

では、なぜ私の答えは間違っているのでしょうか? これらのクエリの違いはですか? DBエンジンレベルで、彼らは正確に何をしますか?

4

2 に答える 2

27

では、なぜ私の答えは間違っているのでしょうか?

あなたの答え正しいです。

先生が間違っているとマークした理由は、その質問で結合の使用を練習しようとしたためだと思います。しかし、それが意図されていた場合、それは問題の一部であったはずです.

これらのクエリの違いは何ですか

技術的には、それらは実際には異なります。単純なクエリ オプティマイザーを備えた DBMS は、教師の回答からの結合とは異なる方法でサブセレクトを取得します。

優れたオプティマイザーを備えた DBMS が実際に両方のクエリに対して同じ実行計画を考え出すことができても、私は驚かないでしょう。

編集

50000 冊の本、50000 人の著者、および 7 つの異なるジャンルをテストするテストデータを作成しました (オプティマイザは単純にテーブル全体を取得する傾向があるため、数字が小さいほど意味がありません)。このステートメントは 7144 行を返します。

PostgreSQL

実行計画は、「結合」メソッドのいくつかの小さな変更を除いてほぼ同じです。

サブセレクト バージョンの計画は次のとおりです: http://explain.depesz.com/s/eov
結合バージョンの計画は次のとおりです: http://explain.depesz.com/s/aTI

驚くべきことに、結合バージョンのコスト値はわずかに高くなります。

オラクル

どちらのプランも 100% 同一です。

-------------------------------------------------- ------------------------------------
| | ID | 操作 | 名前 | 行 | 行 バイト |TempSpc| コスト (%CPU)| 時間 |
-------------------------------------------------- ------------------------------------
| | 0 | ステートメントを選択 | | | 6815 | 399K| | | 273 (2)| 00:00:04 |
| | 1 | ハッシュユニーク| | | 6815 | 399K| 464K| 273 (2)| 00:00:04 |
|* 2 | ハッシュ結合 | | | 6815 | 399K| | | 172 (2)| 00:00:03 |
|* 3 | テーブルへのアクセスがいっぱい| 予約 | 6815 | 166K| | | 69 (2)| 00:00:01 |
| | 4 | テーブルへのアクセスがいっぱい| 著者 | 50000 | 1708K| | | 103 (1)| 00:00:02 |
-------------------------------------------------- ------------------------------------

使用時の統計を見ると、autotrace何の違いもありません。違いが見られるとは思わないので、トレース ファイルを実際に作成して分析することは気にしませんでした。

book.genreインデックス onが追加されても、状況は実際には変わりません。Oracle は、(100000 行であっても) フル テーブル スキャンに固執します。おそらく、テーブルの幅があまり広くなく、多くの行が 1 ページに収まるためです。

PostgreSQL は両方のステートメントにインデックスを使用しますが、計画間に実際の違いはまだありません。

于 2012-05-18T12:06:05.100 に答える
16

どちらのクエリも有効で、同じものを返します。

MySQLあなたの先生はかなり時代遅れの (まだ有効ではありますが) 結合構文を使用しており、一部のデータベース (たとえば、 ) では効率の悪い構文を使用しています。

私があなたの先生だったら、クエリを次のように書きます。

SELECT  DISTINCT name
FROM    books b
JOIN    authors a
ON      a.title = b.title
WHERE   b.genre = 'romance'

MySQLただし、コースが最適化に特化していない場合は、あなたとあなたの教師の両方の質問を受け入れます。

先生が注意を払うことについて言ったのは、その意味ではないでしょうか?

アップデート:

DB エンジン レベルでは、DB エンジンがMySQL.

ではMySQL、あなたのクエリはリーディング テーブルとして強制的に使用Authorsされますが、教師のクエリの場合、オプティマイザはテーブルの統計に応じてどのテーブルをリーディングにするかを選択できます。

于 2012-05-18T11:57:55.243 に答える