2012-03-20 26 views
1

私は2つのテーブルを結合しました。それは本当に本当に遅く、私はなぜ見つけることができません。 非常に大きなクライアントのPRODUCTION環境では、クエリに何時間もかかります。 なぜそれがうまくいかないのか理解する必要があるのですか? インデックスを追加したり、テーブルを分割したりできます。これはOracle 10gです。 私は数千のレコードを期待しています。 !次の条件のため: f.eif_campo1 = c.fornitura ANDとf.field29 =「新規」 Infactは、次のレコードの全18万レコードOracle:表領域の断片化を検出するにはどうすればよいですか?

SELECT c.id_messaggio 
      ,f.campo1 
      ,c.f 
    FROM 
      flows c, 
      tab f 
    WHERE 
       f.field198     = c.id_messaggio 
      AND f.extra_id  = c.extra_id 
      and f.field1     != c.ExampleF 
      and f.field29     = 'New' 
      and c.processtype   in ('Example1') 
      and c.flag_ann     = 'N'; 

選択性は、のように表現するためには、常に確認する必要があります個別値の数:!

COUNT (DISTINCT extra_id)      =>17*10^6, 
COUNT (DISTINCT (extra_id || field20)) =>17*10^6, 
COUNT (DISTINCT field198)         =>36*10^6, 
COUNT (DISTINCT (field19 || field20))    =>45*10^6, 
COUNT (DISTINCT (field1))         =>18*10^6, 
COUNT (DISTINCT (field20))        =>47 

これは、実行計画である[大きな画像を参照してください] [1] [ここに画像の説明を入力します] [2]


詳細: 私はいくつのレコードが取られているかを見るために1つのcontitionをリラックスしています。 30万。

[ここで、画像の説明を入力] [7]

--03:!(24 F)、並列実行/ * +パラレル(C 8)平行と57分*/

--395.358行

SELECT  count(1) 
    FROM 
      flows c, 
      flet f 
    WHERE 
       f.field19     = c.id_messaggio 
      AND f.extra_id  = c.extra_id 
      and f.field20     = 'ExampleF' 
      and c.process_type   in ('ExampleP') 
      and c.flag_ann     = 'N'; 
+2

クエリによって返される行の数はいくつですか? – Ben

+0

私は数千の記録を期待しています。この条件のため:f.eif_campo1!= c.flh_fornitura。事実、それは1800万レコードすべてについて常に検証されるべきです。 – Revious

+0

@ Gik25:この条件がなければ、何行目を期待しますか? –

答えて

1

簡単な答えはあなたの説明計画のようです。両方のテーブルにアクセスしていますby index rowid。 1つの行を選択するのは私の知る限り速くできませんが、あなたの場合は1つの行以上を選択しています。

これは、すべての単一の行のためにあなたは、あなたが何をしたいのかではありませんあなたは、テーブルまたはインデックスのかなりの割合を探している時、で両方のテーブルに1行を行っていることを意味します。

私の提案は、あなたのテーブルのいずれかのfull scanまたは両方を強制することです。最初のドライバーとして小さいを使用してみてください:

SELECT /*+ full(c) */ c.flh_id_messaggio 
    , f.eif_campo1 
    , c.f 
    FROM flows c, 
    JOIN flet f 
    ON f.field19 = c.flh_id_messaggio 
    AND f.extra_id = c.extra_id 
    AND f.field1 <> c.f 
WHERE ... 

しかし、あなたは/*+ full(c) full(f) *//*+ full(c) */を変更する必要があります。

インデックスは別々の列インデックスであるようです。

  • flowsfield19, extra_id, field1flet
  • id_messaggio, extra_id, fの:このために、可能であれば、私は上のインデックスを持っているでしょう。

あなたはフルスキャンとして使用していない場合にのみ、本当に問題になります。または、あなたが戻ってきて選択しているものがすべて1つのインデックスにある場合は、

+0

私が理解できないのは、なぜrowidによる300000アクセスが長引くのかということです。アクセスごとに10ミリ秒かかるので、40分以上かかることはありません。パーティショニングについてどう思いますか?そして、表領域の断片化を測定するのはどうですか? – Revious

+0

@ Gik25、倍のもの(2つのテーブルがあります)。パーティショニングは、180mの行テーブルをテストする価値があります。私は表スペースの断片化の意味を理解していません。あなたはテーブルを意味しますか?私は私の答えで提案された単純な解決策を試みるでしょう。 – Ben

1

あなたの説明書は以下の通りです。

  1. データベース flh_tipo_processo_cod in ('VT','VOLTURA_ENI','CC')
  2. ENI_FLUSSI_HUBから行を取得するためにインデックスを使用その後flh_flag_ann = 'N'
  3. これは基づいETL_ELAB_INTERF_FLATから 行にアクセスするために使用される結果セットを生成する行 をwinnows f.idde_identif_dati_ext_id = c.idde_identif_dati_ext_id
  4. 最後に、これらの行は、WHERE句の残りの部分に基づいてフィルタリングされます。今

flh_tipo_processo_codが選択 列であれば、出発点は良いものです:それは異なる値の数百人が含まれている場合には、ある、または リスト内の値は比較的稀である場合。それはフラグ列の良いパスかもしれません 'N'の値を持つ比較的少数の列を識別します。だから、 あなたのデータのディストリビューション(あなたが持っているいくつの異なる値があるか)と、その値が非常によく見えるかほとんどないかを理解する必要があります。 全体のパフォーマンスは、 flh_tipo_processo_codおよびflh_flag_ann列の分布および/またはスキューが良好でないことを示唆しています。

あなたは何をすることができますか? 1つのアプローチは、ベンの提案に従うことであり、完全な テーブルスキャンを使用することです。 Enterprise Editionのライセンスと十分なCPU容量のある をお持ちの場合は、パラレル問合せを試して改善することができます。これはまだ遅すぎるかもしれません、またはそれは他のユーザーのためにあまりにも破壊的かもしれません。

代わりの方法は、より良いインデックスを使用することです。 eni_flussi_hub(flh_tipo_processo_cod,flh_flag_ann,idde_identif_dati_ext_id, flh_fornitura,flh_id_messaggio)の複合インデックスは、そのテーブルを読み取る必要がありません。 これが新しいインデックスであるかENI_FLK_IDX3の代替であるかは、テーブルに対する他の アクティビティによって異なります。索引圧縮の恩恵を受ける可能性があります。

クエリ投影のすべての列は、WHERE句で参照されます。したがって、 では、他のテーブルのコンポジットインデックスを使用してテーブルの読み込みを回避することもできます。 Agsinでは、データの分布とスキューを理解する必要があります。しかし、おそらく、最も選択的でない列を使用するべきでしょう。 etl_elab_interf_flat(etl_elab_interf_flat,eif_campo200,dde_identif_dati_ext_id,eif_campo1,eif_campo198)のようなものです。おそらく、これは新しいインデックスです。 ETL_EIF_FK_IDX4をこれに置き換えたいとは思わないでしょう(特に、それが実際に外部キー制約のインデックスである場合は特にそうです)。

もちろん、これは私の一部の推測です。チューニングは科学であり、適切に行うには多くのデータが必要です。 the Wait Interfaceを使用して、データベースの所要時間を調査してください。オプティマイザが選択を行う理由を理解するには、the 10053 eventを使用してください。しかしとりわけ、は、実際に分かりませんが分からない限り、パーティション化を実装していません。

関連する問題