ホームページ  >  記事  >  データベース  >  SQL ステートメントの最適化に関する簡単な説明

SQL ステートメントの最適化に関する簡単な説明

伊谢尔伦
伊谢尔伦オリジナル
2016-12-03 11:07:27896ブラウズ

(1) 最も効率的なテーブル名の順序を選択します (ルールベースの seo/' target='_blank'> オプティマイザーでのみ有効):
ORACLE のパーサーは FROM 句を右から左の順序で処理します。 FROM 句内のテーブル名FROM 句に複数のテーブルが含まれる場合、ベースとなるレコードの数が最も少ないテーブルを選択する必要があります。クエリを結合するテーブルが 3 つ以上ある場合は、交差テーブルをベース テーブルとして選択する必要があります。
(2) WHERE 句の接続シーケンス。 :
ORACLE は WHERE 句を解析するためにボトムアップ順序を使用します。この原則に従って、テーブル間の接続は他の WHERE 条件より前に書き込む必要があり、最大数のレコードを除外できる条件は WHERE の最後に書き込む必要があります。
(3) SELECT 句で '*' を使用しないでください:
ORACLE は、解析プロセス中に '*' をすべての列名に順番に変換します。つまり、この作業はデータ ディクショナリをクエリすることによって完了します。時間
(4) get='_blank'> データベースへのアクセス数を削減します:
ORACLE は、SQL ステートメントの解析、インデックス使用率の推定、変数のバインド、データ ブロックの読み取りなどの多くの作業を内部で実行します
(5) ) SQL*Plus、SQL*Forms、および Pro*C の ARRAYSIZE パラメータをリセットして、get='_blank'> データベース アクセスごとに取得されるデータの量を増やします。 推奨値は 200 です
(6) DECODE 関数を使用します。処理時間を短縮します:
同じレコードを繰り返しスキャンしたり、同じテーブルを繰り返し接続したりすることを避けるために、DECODE 関数を使用します。
(7) 単純な非結合の get='_blank'> データベース アクセスを統合します。
複数の単純な get がある場合。 ='_blank'>データベース クエリ ステートメントは、(それらの間に関係がない場合でも) 1 つのクエリに統合できます
(8) 重複レコードの削除:
重複レコードを削除する最も効率的な方法 ( ROWID) 例:
DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP 記録時、通常の状況では、回復可能な情報を保存するためにロールバック セグメントが使用されます。 COMMIT トランザクションの場合、ORACLE はデータを削除前の状態に復元します (正確には、削除コマンドの実行に復元します (以前の状況)) TRUNCATE が使用されると、ロールバック セグメントには復元可能な情報が格納されなくなります。コマンドは実行されますが、データは復元できません。そのため、呼び出されるリソースはほとんどなく、実行時間は非常に短くなります。(翻訳編集者注: TRUNCATE はテーブル全体を削除する場合にのみ適用されます。TRUNCATE は DML ではなく DDL です)
(10) ) 可能な限り COMMIT を使用します:
可能な限り、プログラム内で COMMIT を使用します。これにより、プログラムのパフォーマンスが向上し、COMMIT によって解放されるリソースによって需要が軽減されます。 COMMIT によって解放されるリソース:
a. ロールバック セグメントのデータを回復するために使用される情報
c. REDO ログ バッファー内のスペース
d. ORACLE は、上記 3 つのリソースの内部コストを管理します。 ) HAVING 句を Where 句に置き換えます。
HAVING 句の使用は避けてください。HAVING は、WHERE を通じてレコードの数を制限できる場合、すべてのレコードを取得した後にのみ結果セットをフィルタリングします。 (Oracle 以外の場合) on、where、having の 3 つの句で条件を追加できます。on is It が最初に実行され、次に where と Have last が続きます。カウントする前に条件を満たさないレコードを削除することで、中間操作で処理するデータを減らすことができます。論理的に言えば、これが最も高速になるはずです。合計を実行する前にデータをフィルター処理するため、より高速になるはずです。 、および 2 つのテーブルが結合されている場合にのみ on を使用します。したがって、1 つのテーブルを使用する場合は、where と have のみが比較されます。単一テーブルのクエリ統計の場合、フィルターされる条件に計算されるフィールドが含まれていない場合、結果は同じですが、ラッシュモア テクノロジーを使用できる部分とそうでない部分を除き、後者の方が速度が遅くなります。計算フィールドを関与させるということは、計算前にこのフィールドの値が不確実であることを意味します。前回の記事で書いたワークフローによれば、where のアクションは計算後に完了します。この場合、2 つの結果は異なります。複数テーブルの結合クエリでは、on は where よりも早く有効になります。システムは、まず各テーブル間の接続条件に基づいて複数のテーブルを一時テーブルに結合し、次に where でフィルタリングし、計算後、have でフィルタリングします。フィルター条件に正しい役割を持たせたい場合は、まず条件がいつ有効になるかを理解し、それからどこに配置するかを決定する必要があることがわかります
(12) テーブル クエリを減らす:
サブクエリを含む SQL ステートメントでは、テーブルへのクエリを減らすことに特に注意してください。 例:
SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME, DB_VER) = ( SELECT
TAB_NAME, DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
(13) 内部関数を通じて SQL 効率を向上させます。:
複雑なSQLは実行効率が犠牲になることが多いので、上記の関数を使って問題を解決する方法をマスターできることは、実際の作業において非常に有意義です
(14) テーブルの別名(Alias)を使用する:
SQL ステートメントで複数のテーブルを接続する場合は、テーブルのエイリアスを使用し、そのエイリアスを各列に接頭辞として付けてください。これにより、解析時間を短縮し、列の曖昧さによって引き起こされる構文エラーを減らすことができます。
(15 ) IN を置換します。 with EXISTS および NOT IN with NOT EXISTS:
基本テーブルに基づく多くのクエリでは、条件を満たすために、多くの場合、別のテーブルを結合する必要があります。この場合、EXISTS (または NOT EXISTS) を使用すると、一般に、サブクエリでは、NOT IN 句により内部ソートとマージが実行されます (サブクエリ内のテーブルに対して内部ソートが実行されるため)。 NOT IN の使用を回避するには、外部結合 (Outer Joins) または NOT EXISTS に書き換えます。
(効率的) SELECT * FROM EMP (ベース テーブル) WHERE EMPNO > AND EXISTS (SELECT 'X ' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = 'MELB')
(非効率) SELECT * FROM EMP (ベース テーブル) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = 'MELB')
(16) 「非効率な実行」SQL ステートメントを特定します。
SQLseo/' target='_blank'> 最適化のためのさまざまなグラフィカル ツールが無限に登場していますが、独自の SQL ツールを作成してください。問題を解決するのは常に最善の方法です。
SELECT EXECUTIONS, DISK_READS, BUFFER_GETS,
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,
SQL_TEXT
FROM V$ SQLAREA
WHERE EXECU TIONS>0
AND BUFFER_GETS> ; 0
AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS ORDER BY 4 DESC;
(17) インデックスを使用して効率を向上させる:
インデックスはテーブルの概念的な部分であり、データの取得の効率を向上させるために使用されます。 , ORACLE は、複雑な自己分散型 B ツリー構造を使用しており、インデックスを使用したデータのクエリは、クエリと Update ステートメントを実行するための最適なパスを見つけるとき、ORACLEseo/' target='_blank'> より高速です。オプティマイザーはインデックスを使用します。インデックスを使用すると、主キーの一意性が検証されるため、複数のテーブルを結合する際の効率も向上します。 LONG または LONG RAW データ型では、ほとんどすべての列にインデックスを付けることができます。もちろん、インデックスを使用すると、小さなテーブルをスキャンするときにも効率が向上します。効率は向上しますが、そのコストにも注意する必要があります。テーブル内でレコードが追加または削除されるか、インデックス列が変更されると、インデックス自体も変更されることになります。各レコードの INSERT、DELETE、および UPDATE にはさらに 4 ~ 5 回のディスク I/O が必要になるため、インデックスには追加のストレージ領域と処理が必要となり、これらの不必要なインデックスによってクエリの応答時間が実際に遅くなります。インデックスの定期的な再構築が必要です。:
ALTER INDEX REBUILD
18) DISTINCT を EXISTS に置き換えます:
1 対多のテーブル情報 (部門テーブルや従業員テーブルなど) を含むクエリを送信する場合は、SELECT 句を使用しないでください。 DISTINCT を使用します。例:
(非効率):
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM を使用すると、EXIST を置き換えることを検討できます。 DEPT D , EMP E
WHERE D.DEPT_NO = E.DEPT_NO
(効率的):
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT 'X'
FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
( 19) Oracle は常に、server/' target='_blank'>sql ステートメントを最初に解析し、小文字を大文字に変換してから実行するため、server/' target='_blank'>sql ステートメントは大文字になります。 ( 20) Java コード内の文字列を接続する場合は、コネクタ「+」をできるだけ使用しないでください。
(21) インデックス列での NOT の使用は避けてください。一般的に、NOT はインデックス列での関数の使用と同じ影響を及ぼします。ORACLE はインデックスの使用を停止し、実行します。
(22) インデックス列での計算の使用を避けてください。
WHERE 句で、インデックス列が関数の一部である場合。 seo/' target='_blank'>オプティマイザはインデックスを使用せず、テーブル全体のスキャンを使用します。
例:
非効率:
SELECT … FROM DEPT WHERE SAL * 12 > 25000;
効率的:
SELECT … FROM DEPT WHERE SAL > 25000/12;
(23)> の代わりに >= を使用します。 SELECT * FROM EMP WHERE DEPTNO >=4
非効率:
SELECT * FROM EMP WHERE DEPTNO >3
2 つの違いは、前者の DBMS は DEPT が 4 の最初のレコードに直接ジャンプするのに対し、後者は最初に DEPTNO=3 のレコードを見つけて、DEPT が 3 より大きい最初のレコードまで前方スキャンします。
(24) OR を UNION に置き換えます (インデックス列に適用されます)
通常、WHERE 句の OR を UNION に置き換えると、より良い結果が得られます。インデックス列に OR を使用すると、テーブル全体がスキャンされます。インデックスが作成されていない列がある場合、OR を選択しなかったためにクエリの効率が低下する可能性があることに注意してください。以下の例では、インデックスは LOC_ID と REGION の両方に基づいて構築されます。
効率的:
SELECT LOC_ID、LOC_DESC、REGION
FROM LOCATION
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE REGION = "MELBOURNE"
非効率:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ ID = 10 または地域 = 「メルボルン」
どうしても OR を使用する場合は、返されるレコードが最も少ないインデックス列を最初に書き込む必要があります。
(25) IN を使用して OR を置き換えます
これはシンプルで覚えやすいルールですが、実際の実行は効果をテストする必要がありますが、ORACLE8i では、2 つの実行パスは同じであるようです。
非効率:
SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30
効率的
SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30);
(26) インデックス列 IS NULL での使用を避けるそして IS NOT NULL
インデックス内で NULL 許容カラムを使用しないでください。ORACLE はインデックスを使用できなくなります。単一列インデックスの場合、列に NULL 値が含まれる場合、レコードはインデックスに存在しません。複合インデックスの場合、少なくとも 1 つの列が NULL の場合、そのレコードもインデックスに存在しません。 null ではない場合、レコードはインデックスに存在します。例: テーブルの列 A と B に一意のインデックスが構築されており、A と B の値が (123、null) であるレコードがテーブルにある場合、ORACLE は同じ A を持つ次のレコードを受け入れません。ただし、すべてのインデックス列が null の場合、ORACLE はキー値全体を null とみなし、null は null と等しくないため、1000 件のレコードを挿入できます。同じキー値であり、もちろんすべて null です。! null 値はインデックス列に存在しないため、WHERE 句でインデックス列を比較すると、ORACLE はインデックスを非アクティブ化します。インデックスが無効です)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
効率的: (インデックスが有効)
SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;
(27) 常にインデックスの最初の列を使用します。複数の列で構築されますが、その中の最初の列のみです。列 (先頭の列) が where 句によって参照される場合、seo/' target='_blank'> オプティマイザーはインデックスの使用を選択します。ただし重要なルールは、インデックスの 2 番目の列のみが参照される場合です。 seo/' target='_blank'> オプティマイザはテーブル全体のスキャンを使用し、インデックスを無視します
28) UNION を UNION-ALL に置き換えます (可能な場合) :
SQL ステートメントで 2 つのクエリ結果セットの UNION が必要な場合、2 つの結果セットは UNION-ALL 方式でマージされ、最終結果を出力する前にソートされます。UNION の代わりに UNION ALL が使用される場合、ソートは必要ありません。効率が向上します。 はい、UNION ALL は 2 つの結果セットで同じレコードを繰り返し出力します。そのため、UNION が結果セットを並べ替える可能性を分析する必要があります。この操作では SORT_AREA_SIZE メモリが使用されます。SEO/' target='_blank'> の場合、次の SQL を使用して並べ替えの効率を確認できます:
SELECT ACCT_NUM, BALANCE_AMT。
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION
SELECT ACCT_NUM、BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
効率的:
SELECT ACCT_NUM, BALANCE_AMT
DEBIT_TRANSACTIONS
からTRAN_DATE = '31 -DEC-95'
UNION ALL
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
(29) ORDER BY を WHERE に置き換えます:
ORDER BY 句は 2 未満のインデックスのみを使用します厳格な条件。
ORDER BY のすべての列は同じインデックスに含まれ、インデックス内の並べ替え順序を維持する必要があります。
ORDER BY のすべての列を指定する必要があります

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。