0

私は、人々が何年にもわたって私にさまざまな答えをくれたという基本的にSQL選択の質問をしています。それぞれが 40 列を超えるように設計された 2 つのテーブルがあり、潜在的に 10 から数千の行を保持するとします。私は SqlServer2005 を使用しています。

これらのテーブルを結合するとき、where句で次のようなものがある場合

select * from t1, t2
where t1.UserID = 5 
and t1.SomeID = t2.SomeOtherID

一部の人々は、「t1.SomeID = t2.SomeOtherID」の後ではなく、定数「t1.UserID = 5」を常に前に置くべきだと言います。これにより、選択のパフォーマンスが向上します。他の人はそれは問題ではないと言いますが。

正解は?

また、ADO.NET Entity Framework を使用して DAL を実装する場合、40 を超える列を持つテーブルをモデル化し、CRUD 操作を実行すると、パフォーマンスの問題が発生しますか?

ありがとうございました、

レイ。

4

4 に答える 4

4

一般に、データベースの最適化では、最初に概念的に正しい SQL を記述してから、プロファイリングで必要であることが示された場合にパフォーマンスを微調整する必要があります。内部結合を行う場合は、デカルト積よりも SQL-92 の明示的な INNER JOIN を使用することをお勧めします。だから私はあなたのSQLを次のように書くことから始めます:

SELECT * 
FROM t1
  INNER JOIN t2
    ON t1.SomeID = t2.SomeOtherID
WHERE
  t1.UserID = 5 

INNER JOIN の ON 部分に入る t1.SomeID = t2.SomeOtherID は、2 つのテーブル間の関係を表すためです。結果セットを制限するためのフィルターであるため、WHERE 句に入る UserID。このように SQL を記述すると、結合とフィルタリングに関する意図が表現されるため、データベース オプティマイザーにより多くの情報が提供されます。

実際のデータベースでこの構文を使用しても許容できるパフォーマンスが得られない場合は、自由にビットを移動してみてください。しかし、私が言ったように、概念的に正しいものから始めてください。

質問の 2 番目の部分に関して、最も明白なパフォーマンスへの影響は、エンティティのコレクションを選択するときに、Entity Framework が実体化するエンティティのすべてのプロパティを戻す必要があることです。したがって、40 個の列がある場合、それらをエンティティとして実体化すると、そのデータをワイヤ経由でプルすることになります。ただし、必要な列のみを含む匿名型を返す LINQ クエリを作成することは可能です。ただし、完全な CRUD を行うには、エンティティを返す必要があります。

于 2008-12-17T22:46:00.100 に答える
2

RDBMSクエリの最適化は時間の経過とともに進化し、RDBMSが異なればアプローチも異なるため、これに関する人々の意見は時間とともに変化します。私はそこにあるすべてのシステムについて話すことはできませんが、2008年にこれが何か違いを生むことは本当にありそうにありません。特定のシステムのみに関心がある場合はYMMV。

Oracleの最近のバージョンでは、違いはありません。

于 2008-12-18T17:30:49.223 に答える
0

まず、デカルト積ではなく、明示的な JOIN 構文を使用してクエリを作成します。おそらく、最新のオプティマイザーのパフォーマンスに関しては何の違いもありませんが、JOIN がどのように機能するかに関する情報がプログラマーにとってよりアクセスしやすくなります。


SELECT Player.Name, Game.Date
 FROM Player
  INNER JOIN Game ON Game.WinnerPlayerID = Player.PlayerID
 WHERE Game.WinnerFrags > Game.TotalFrags/2
 ORDER BY Player.Name

これにより、ゲーム内の他のすべてのプレーヤーを合わせたよりも多くのフラグを獲得したすべてのプレーヤーと、ゲームの日付が名前でソートされます。いずれにせよオプティマイザは JOIN の一部としてフィルタリングを実行する可能性が高いため、両方の条件を JOIN に配置しても、おそらくパフォーマンスには影響しません。ただし、LEFT JOIN にとっては問題になり始めます。今週の上位 10 人のプレイヤーが、上記の差で勝ったゲームの数を探しているとしましょう。それらのいくつかはこれほど見事に 1 つも持っていない可能性があるため、LEFT JOIN が必要になります。


SELECT Player.WeekRank, Player.Name, COUNT(Game.*) AS WhitewashCount
 FROM Player
  LEFT JOIN Game ON Game.WinnerPlayerID = Player.PlayerID
 WHERE Player.WeekRank >= 10
  AND Game.WinnerFrags > Game.TotalFrags/2
 GROUP BY Player.WeekRank, Player.Name
 ORDER BY Player.WeekRank

まあ、そうではありません。JOIN は、プレイヤーがプレイした各ゲームのレコードを返します。プレイヤーがゲームをプレイしていない場合は、プレイヤー データと NULL ゲーム データを返します。これらの結果は、フラグメント基準に基づいて、オプティマイザーの決定に応じて、結合中または結合後にフィルター処理されます。これにより、frag 基準を満たさないすべてのレコードが削除されます。そのため、これほど壮観な勝利を収めたことのないプレイヤーをグループ化する記録はありません。INNER JOIN の効果的な作成 .... 失敗。


SELECT Player.WeekRank, Player.Name, COUNT(Game.*) AS WhitewashCount
 FROM Player
  LEFT JOIN Game ON Game.WinnerPlayerID = Player.PlayerID
   AND Game.WinnerFrags > Game.TotalFrags/2
 WHERE Player.WeekRank >= 10
 GROUP BY Player.WeekRank, Player.Name
 ORDER BY Player.WeekRank

Frag 基準を JOIN に移動すると、クエリは正しく動作し、ホワイトウォッシュを達成したかどうかに関係なく、その週のトップ 10 のすべてのプレーヤーのレコードが返されます。

結局のところ、短い答えは次のとおりです。

INNER JOIN の状況では、条件をどこに置いてもパフォーマンスの違いはおそらくありません。ただし、結合条件とフィルタリング条件を分離すると、クエリが読みやすくなります。そして、間違った場所で条件を取得すると、LEFT JOIN の結果が大きく損なわれる可能性があります。

于 2008-12-29T15:25:58.713 に答える