web-dev-qa-db-ja.com

カウントが遅いOracle

これは私のクエリです:

SELECT Count(last_upd)
FROM S_CONTACT
WHERE last_upd_by = '0-1' AND LAST_NAME <> 'Wait' AND last_upd  +  1/24 > SYSDATE - (1 / (24 * 60));

この結果が返されるまでに84秒かかります。

COUNT(LAST_UPD)
---------------
43

返された43行だけではなぜ遅いのかわかりません...

これは実行計画です:

Ecxecution plan

誰か助けてもらえますか?これはV $ STATNAMEです

クリーンアウト中のアクティブなtxnカウント1 
バイトは、SQL * Netを介してクライアントから受信しました497 
バイトはSQL * Netを介してクライアント14803に送信しましたkcmgss 23 
 kcmgasへの呼び出し45 
クリーンアウト-ktugct呼び出しの数12 
クリーンアウトとロールバック-一貫した読み取りは2 
クリーンアウトのみ-一貫した読み取りは10 
クリーンアウト中のtxnカウントのコミット11 
一貫した変更450 
一貫した取得1458915 
一貫した取得-検査458 
キャッシュからの一貫した取得1458915 
このセッションで使用されるCPU 4485 
通話開始時に使用されたCPU 4493 
 CRブロックが作成されました44 
現在のブロックがCR 1 
カーソル認証1 
に変換されましたデータブロックの一貫した読み取り-適用されたレコードの取り消し59 
 dbブロックの変更12 
 DB時間8383 
ダーティバッファーの検査31 
エンキューリリース1 
エンキューリクエスト1 
実行カウント2 
空きバッファ入力影響あり1442014 
空きバッファが要求されました1436612 
ヒープブロック圧縮12 
ホットバッファがLRU 25764 
即時(CR)ブロッククリーンアウトアプリケーション12 
作業なし-一貫した読み取りで1458380 
開いたカーソルの累積2 
 OS非自発的コンテキストスイッチ18069 
 OS最大常駐セットサイズ1956 
 OSページフォールト4 
 OSページの再利用410 
使用されたOSシステム時間1868 
使用されたOSユーザー時間2625 
 OS自発的コンテキストスイッチ63594 
解析カウント(ハード)1 
解析カウント(合計)2 
物理読み取りバイト11768365056 
物理読み取りIO要求55724 
物理読み取り合計バイト11768365056 
物理読み取り合計IOリクエスト55724 
物理読み取り合計マルチブロックリクエスト54675 
物理読み取り1436568 
物理読み取りキャッシュ1436568 
物理読み取りキャッシュプリフェッチ1380844 
プリフェッチされたブロックが使用前に期限切れ8 [._ ___。]再帰呼び出し1 
 redoエントリ12 
 redoサイズ1272 
 redo subscn最大カウント8 
ロールバックのみ-一貫した読み取りは40 
セッションを取得します論理読み取り1458915 
セッションpgaメモリ-393216 
セッションpgaメモリ最大262144 
セッションugaメモリ最大299256 
共有ハッシュラッチアップグレード-待機なし4 
 sorts(memory)2 
 sorts(rows)760 
 SQL * Net clienttrips to/from client 9 
 table scan blocks getten 1458432 
 table scan rows gotd 16656961 
テーブルスキャン(長いテーブル)1 
トランザクションテーブルの一貫した読み取りロールバック4 
トランザクションテーブルの一貫した読み取り-適用されたレコードを元に戻す391 
ユーザーコール11 
ユーザーI/O待機時間6172 
ワークエリア実行-最適5 

Oracle Database 10g Enterprise Editionリリース10.2.0.4.0-64ビットを使用しています

ありがとうございました

2
Adeel ASIF
  • クエリは43行を返さず、番号43を含む1行を返します
  • クエリの実行時間は、返される行数ではなく、検査する行数に依存します。
  • クエリプランから、クエリが全テーブルスキャンを実行していることがわかります。つまり、テーブルを最初から最後まで読み取り、テーブルの1600万行すべてを読み取ります(table scan rows gotten 16656961)。
  • このため、約11Gデータ(物理的な読み取りの合計バイト数 11768365056)を読み取り、55,000回の読み取り操作を実行する必要があります(物理的な読み取りの合計IOリクエスト 55724)。60秒で55,000回の読み取り(ユーザーI/O待機時間 6172)は、読み取りあたり1.1ミリ秒を意味します。これは適切な値です。

クエリが処理する必要がある行の数を減らす必要があります。インデックスは、Oracleが関心のあるRowaの数を効率的にカウントするのに役立ちます。

  • where-clauseの最も選択的な副次句はlast_upd副次句になります。したがって、この列にインデックスを作成します。
  • 他のwhere-clauses(およびselect-clauses)の列もインデックスに追加する必要があります。したがって、Oracleはlast_upd_byとlast_nameの値を取得するために、テーブルのインデックスによって検出されたフィッティング行をそれぞれ検索する必要はありません。
  • last_upd_by副次句は、次の選択句なので、インデックスの次の列にする必要があります。したがって、この順序で列(last_updlast_upd_bylast_name)にinexを作成する必要があります。
3
miracle173

提供された統計によると、ユーザーI/O待機時間は、db時間8383のうち6172です。

「ユーザーI/O」が主要な待機イベントとして表示される場合は、SQLチューニングが最善の答えであり、特に欠落しているインデックスを追加します。プランはフルテーブルスキャンを使用していることを示しているため、where句で使用されている列にインデックスを追加できます。

2
JSapkota

次のインデックスを作成してみてください。

CREATE INDEX s_contact_idx_001
    ON s_contact_lupd_lastupdby_name 
     ( last_upd, last_upd_by, last_name );

命名規則に対応するように名前を変更し、一意であることを確認してください。

2
Gandolf989