サーバーに送信するすべてのSQLクエリは、三つのステージ(SELECTの場合は四つ)を通過する必要があります。 まず、Oracleはライブラリ-キャッシュ内で一致するSQLハッシュを検索します。 ハッシュが見つかった場合は、関連するexplain計画を取得して実行します。 そうでない場合は、ハード解析が呼び出されます->これは、次のステップが実行されることを意味します。
- 構文解析
- 構文チェック
- セマンティクスチェック
- 権限チェック
- BIND
- bind/host変数を実際の値に置き換えます
- EXEC
- explain計画に基づく実際の実行
- FETCH(SELECTステートメントのみ)
- は、ユーザーに結果セットを返します
次の例で各フェーズを説明しましょう。
このクエリを実行しました:
SELECT *FROM employee;
サーバープロセスは、ISSUES SQLクエリのハッシュを生成します。 ハッシュは、SQLクエリのテキストに基づいて生成される16進値です。 ここでは非常に重要な部分が来る!! わずかな変更(大文字から小文字、またはその逆、スペースの追加/削除、…)でもハッシュが変更されるため、ハード解析が生成される可能性があります(以下のハー あなたは非常に注意して、1つのコードだけに固執しようとする必要があります–それがプロシージャが最もうまくいく理由です(その上で–彼らは主に
以下のクエリを実行することで、自分で簡単に確認できます:
-- first run this querySELECT * FROM dual;-- then run this one again with all uppercase lettersSELECT * FROM DUAL;-- check the sql hashes SELECT sql_id, sql_text, hash_valueFROM v$sqlWHERE 1=1AND lower(sql_text) LIKE '%select%from dual%'; sql_id | sql_text | hash_value--------------------------------------------------0x735fvggtnu6 | SELECT * FROM DUAL | 37411111103vyt9wdmca69b | SELECT * FROM dual | 1724193067-- As you can see Oracle evaluated it as two different queries.
ハッシュが生成されると、Oracleはこの問合せがこのインスタンスで既に実行されているかどうかを確認します。 どう? ハッシュがSQL領域に既に存在するかどうかを確認します。
このクエリがまだ利用できないと仮定すると、このクエリのハッシュ値で作成されたSQL領域があり、Oracleはクエリ処理の最初の段階を開始し、それがPARSE
- 構文チェック中、Oracleはクエリが構文的に正しいかどうかをチェックします(SELECTの代わりにSELECT;コマンドの正しい順序->SELECT*FROM table ORDER BY col1WHERE col2=’John’;など)。
- 次のステップは、列名とオブジェクト名が正しいかどうかをOracleが検証するセマンティクス-チェックです。 どう? PARSEステージの最後のステップで、データ-ディクショナリ-キャッシュ
- とクロスチェックすることにより、Oracleは、ユーザー/アプリケーションが照会されたオブジェク
これが終わると、SQL領域が有効になり、OPTIMIZERと呼ばれるOracleの別のツールが実行計画を生成します。 最適な実行計画が選択されると、Oracleはすべての変数をバインドし、3番目のステップである実行に進みます。
ここで何が起こるのですか? Oracleは、照会されたオブジェクトに関連するデータ-ブロックを読み取り、バッファ-キャッシュに転送します(まだそこに表示されていない場合)。 彼らがそこにいる場合、Oracleはそれらを再び読まないでしょう!). このプロセスはI/Oを生成します(記事Computing Architectureで述べたように、メモリからの読み取りに比べて非常に遅いです)。 私はしばらくここで停止し、I/Oの生成を強調します。 ソフト解析の場合、すべてのデータはディスクから読み取るよりもはるかに高速なメモリ(バッファキャッシュ)から読み取られます。 そのため、可能な限りクエリをリサイクル/再利用するよう努力する必要があります。 クエリを変更するたびに新しいハッシュが生成されるため、おそらくI/Oが生成されます。
データが既にメモリ(バッファキャッシュ)にあることSELECTステートメントが処理され、最終段階(フェッチ)がトリガーされ、結果セットがユーザーに返されます。
同じクエリが再び実行されると、ハッシュが生成され、そのハッシュのSQL領域が既に存在するため、PARSEステージはスキップされ、EXECとFETCHのみが実行されます。