5

私は ORM ソリューションの支持者であり、時々 Hibernate に関するワークショップを行っています。

フレームワークで生成された SQL について話すとき、人々は通常、「ヒント」を使用できるようにする必要がある方法について話し始めますが、これはおそらく ORM フレームワークでは不可能です。

通常は、「Hibernate を試してみました。最初は有望に見えましたが、非常に複雑な実稼働データベースで解き放つと、ヒントを適用できなかったため機能しなくなりました!」。

しかし、具体例を問われると、それらの人々の記憶は突然はっきりしなくなります...

「ヒント」のトピック全体が私にはブードゥー教のように聞こえるので、私は通常、怖がっています. SQL ヒントまたは DB ヒントとは何を意味しますか?

私が知っている唯一のことは、どういうわけか「ヒントのような」ものはSELECT ... FOR UPDATEです。しかし、これは Hibernate-API によってサポートされています...

4

5 に答える 5

12

SQL ステートメント、特に複雑なステートメントは、実際には DB エンジンによってさまざまな方法で実行できます (結合内のどのテーブルを最初に読み取るか、さまざまなパラメーターに基づいてどのインデックスを使用するかなど)。

経験豊富なデータベース管理者は、ヒントを使用して、DB エンジンが実行計画を生成するときに特定のメソッドを選択するように促すことができます。通常、これを行う必要があるのは、特定のクエリの広範なテストと分析の後でのみです (DB エンジンは通常、最適な実行計画を見つけるのに非常に優れているため)。

ここでの MSSQL 固有の説明と構文:
http://msdn.microsoft.com/en-us/library/ms181714.aspx

編集:
http://geeks.netindonesia.net/blogs/kasim.wirama/archive/2007/12/31/sql-server-2005-query-hints.aspxの追加の例

于 2008-11-04T14:25:52.347 に答える
9

クエリ ヒントは、既定では適切なクエリ プランが生成されない場合に、クエリ オプティマイザーをガイドするために使用されます。最初に、クエリ オプティマイザーの背景について簡単に説明します。

データベース プログラミングは、機械的なコンポーネントを備えているため、他のほとんどすべてのソフトウェア開発とは異なります。ディスクのシークと回転の待ち時間 (特定のセクターがディスク ヘッドの下に到着するのを待つ) は、CPU に比べて非常にコストがかかります。クエリ解決戦略が異なれば、I/O の量も異なり、多くの場合、根本的に異なる量になります。これが正しいか間違っているかによって、クエリのパフォーマンスに大きな違いが生じる可能性があります。クエリの最適化の概要については、このペーパーを参照してください。

SQL は宣言的です。クエリのロジックを指定し、DBMS に解決方法を理解させます。最新のコストベースのクエリ オプティマイザー (Oracle などの一部のシステムでは、下位互換性のために従来のクエリ オプティマイザーも保持されています) は、クエリに対して一連の変換を実行します。これらはセマンティックな同等性を維持しますが、操作の順序と選択が異なります。テーブルで収集された統計 (サイズ、キーの分散ヒストグラム) に基づいて、オプティマイザーは各クエリ プランに必要な作業量の見積もりを計算します。最も効率的なプランを選択します。

コストベースの最適化はヒューリスティックであり、正確な統計に依存しています。クエリの複雑さが増すと、ヒューリスティックが誤った計画を生成する可能性があり、非常に非効率になる可能性があります。

この状況でクエリ ヒントを使用して、結合の種類など、クエリ プランで特定の戦略を強制することができます。たとえば、通常非常に小さな結果セットを返すクエリでは、ネストされたループ結合を強制したい場合があります。テーブルの特定の結合順序を強制することもできます。

O/R マッパー (または SQL を生成するツール) は独自のクエリを生成しますが、これには通常、ヒント情報はありません。このクエリが非効率的に実行される場合、選択肢は限られています。その一部を次に示します。

  • テーブルのインデックスを調べます。おそらく、インデックスを追加できます。一部のシステム (最近のバージョンの Oracle など) では、複数のテーブルにまたがる結合にインデックスを付けることができます。

  • 一部のデータベース管理システム (やはり Oracle が思い浮かびます) では、クエリ プランを特定のクエリ文字列に手動で関連付けることができます。クエリ プランは、クエリのハッシュ値によってキャッシュされます。クエリがパラメーター化されている場合、基本クエリ文字列は定数であり、同じハッシュ値に解決されます。

  • 最後の手段として、データベース スキーマを変更できますが、これはアプリケーションを制御している場合にのみ可能です。

SQL を制御する場合は、クエリをヒントすることができます。実際には、実際にこれを行う必要があることはほとんどありません。複雑なデータベース スキーマを持つ O/R マッパーのより一般的な障害モードは、複雑なクエリ述語を表現したり、大量のデータに対して複雑な操作を実行したりすることが困難になる可能性があることです。

私は、O/R マッパーが適している 98% の作業に O/R マッパーを使用し、適切なソリューションであるストアド プロシージャにドロップすることを推奨する傾向があります。本当にクエリをヒントする必要がある場合は、これが適切な戦略かもしれません。アプリケーションに通常とは異なる点 (たとえば、ある種の DSS) がない限り、O/R マッパーからエスケープする必要があるのは少数の状況だけです。また、O/R マッパーが実際にはアプリケーションにとって適切な戦略ではないことに気付くかもしれません (ここでも、データを集約して操作する DSS ツールがその例です)。

于 2008-11-04T15:54:27.613 に答える
4

ヒントは他の回答で説明されているように機能しますが、まれに調査された状況でのみ使用する必要があります。HINT の 10 回のうち 9 回は、不適切なクエリ プランになります。自分が何をしているのか本当にわかっていない限り、それらを使用しないでください。

于 2008-11-04T14:31:45.347 に答える
3

最新のすべての RDBMS には、SQL クエリを実行するために必要な一連の読み取り/書き込み操作である最適なクエリ プランを計算する、ある種のクエリ オプティマイザがあります。

計画が最適ではない場合もあるため、RDBMS 設計者は SQL に「ヒント」を含めました。ヒントは、クエリ オプティマイザーに影響を与える SQL に埋め込むことができる命令です。ヒントを使用すると、使用するインデックス、テーブルからデータを読み取る順序など、クエリ オプティマイザーに指示できます。

したがって、ヒントを使用すると、クエリ オプティマイザーだけでは解決できないボトルネックを解決できます。

たとえば、ここにOracle ヒントのリストがあります。

于 2008-11-04T14:27:39.490 に答える
3

SQL コードは決して実行されないため、「最適化された SQL コード」などというものはありません。

SQL コードは、オプティマイザーによって実行計画に変換されます。オプティマイザーは、(とりわけ) 選択する必要がある情報を使用します。

  • テーブルが含まれる順序
  • 関連する各テーブルの結合方法 (ネスト/マージ/ハッシュ)
  • テーブルのデータにアクセスする方法 (テーブルへの直接アクセス/ブックマーク ルックアップによるインデックス/インデックスへの直接アクセス) (スキャン/シーク)
  • 並列処理を使用する必要があるか、いつ並列処理を終了するか (ストリームを収集する)

クエリ ヒントを使用すると、プログラマはオプティマイザの選択を上書き (ほとんどの場合) したり、丁寧に (その他の場合) 提案したりできます。

クエリ ヒントを使用すると、並列処理を強制的に無効にしたり、すべての結合をネストされたループとして実装したり、あるインデックスを別のインデックスよりも優先して使用したりすることができます。たとえば、いくつかの例があります。

オプティマイザーは非常に優れているため、オプティマイザーをオーバーライドすると、通常、最適でない計画を求めていることになります。クエリ ヒントは、適切な選択を行うために必要な情報がオプティマイザーにない場合に最適です。

私がクエリ ヒントを使用する場所の 1 つは、テーブル変数です。テーブル変数はオプティマイザーによって 0 行であると想定されるため、オプティマイザーは常にネストされたループを使用してテーブル変数を結合します (少数の行に最適な結合の実装)。大きなテーブル変数があり、マージ結合に適した方法で既に並べ替えられている場合、クエリ ヒントを適用してマージ結合を使用するように指定できます。

于 2008-11-04T16:50:11.587 に答える