2016-12-13 33 views
1

Oracle SQLクエリでパフォーマンスが非常に低下しています。私は、テーブルibe_partos_mで定義されたインデックス、フィールドcodloteとフィールドcodをしましたテーブルのパフォーマンスが低下します

SELECT distinct idm3.cod 
    FROM ibe_partos_m idm3, ibe_padron_prov_2010_m pad2 
    WHERE  idm3.codLote = 1 
     AND idm3.activo = 1 
     AND ((pad2.ar = '2016' and pad2.mes='1') or (pad2.ar = '2015' and pad2.mes='7')) 
     AND idm3.cod NOT IN     
      (SELECT idm2.cod 
       FROM ibe_partos_m idm2, 
        ibe_padron_prov_2010_m pad 
      WHERE  idm2.codLote = 1 
        AND idm2.activo = 1 
        AND ((pad.ar = '2016' and pad.mes='1') or (pad.ar = '2015' and pad.mes='7')) 
        AND pad.tiden != '2' 
        AND idm2.nombreM = pad.NOMB 
        AND idm2.apell1m = pad.APE1 
        AND idm2.apell2m = pad.APE2 
        AND ( idm2.numdocm = pad.IDEN || pad.LIDEN OR 
           idm2.numdocm = pad.NDOCU OR 
           idm2.numdocm = pad.LEXTR|| pad.IDEN|| pad.LIDEN OR 
           idm2.numdocm = pad.LEXTR || '0' || pad.IDEN|| pad.LIDEN OR 
           idm2.numdocm = pad.lextr || SUBSTR (pad.iden, 2, LENGTH (pad.iden))|| pad.liden) 
       )       
     AND idm3.PROREM = '07' 
     AND idm3.nombreM = pad2.nomb 
     AND idm3.apell1m = pad2.ape1 
     AND idm3.apell2m = pad2.ape2 
     AND ( (pad2.tiden = '1' AND pad2.liden IS NOT NULL) 
       OR ( pad2.tiden = '3' 
        AND pad2.liden IS NOT NULL 
        AND pad2.lextr IS NOT NULL)); 

;:クエリはこれですテーブルibe_padron_prov_2010_mには、フィールドape1,ape2およびidenが含まれています。すべてのインデックスは単純です。

パフォーマンスが悪い理由を理解できません... ape1の2つのインデックスではなく、結合速度を向上させるにはape2で十分ですか?

ありがとうございます!

編集:私が達成しようとしていることはこれです:

  • だがは、内側のSELECTで選択したレコードとして修正されているレコードを定義してみましょう。

  • 私はかつての意味で正しいないレコードを取得しようとしているが、それでもいくつかのプロパティにフィット、であることだ。

    idm3.codLote = 1 
        AND idm3.activo = 1 
        AND ((pad2.ar = '2016' and pad2.mes='1') or (pad2.ar = '2015' and pad2.mes='7')) 
    
    
    
    AND idm3.PROREM = '07' 
        AND idm3.nombreM = pad2.nomb 
        AND idm3.apell1m = pad2.ape1 
        AND idm3.apell2m = pad2.ape2 
        AND ( (pad2.tiden = '1' AND pad2.liden IS NOT NULL) 
          OR ( pad2.tiden = '3' 
           AND pad2.liden IS NOT NULL 
           AND pad2.lextr IS NOT NULL)); 
    

EDIT2:@Craigヤングとして、正確には、私は別のcodを得ることに興味があります(どちらの選択でも)...しかし、一致した場合には、特定のibe_partos_mの検索を停止するようにDBサーバに指示する方法はありますか?

+0

あなたがしようとしていることを説明してください、私はあなたがこのクエリをより良く最適化できると信じてください。 – sagi

+0

元の質問を編集しました、ありがとう! – Alex

+0

Enterpriseヒントでパラレルヒントを使用している場合は、distinctの代わりにgroup byを使用します。あなたが100万の行を持っていて、あなたのインデックスがたくさんの価値の100の "行"から成っている場合、インデックスは非常に高価な方法です – Thomas

答えて

2

JOINを使用すると、わかりやすくコードを読みやすくなります。

LEFT JOINはidm2

とadm2.codヌルであるからすべての行を返すことが保証されます。

SELECT distinct idm3.cod 

あなたはおそらくあなたのクエリで参加するエラーの重複を非表示にするDISTINCTを使用している:

select distinct idm3.cod 
    from ibe_partos_m idm3 

    inner join ibe_padron_prov_2010_m pad2 
    on idm3.nombrem = pad2.nomb 
    and idm3.apell1m = pad2.ape1 
    and idm3.apell2m = pad2.ape2 

    left join (select idm2.cod 
      from ibe_partos_m idm2 
      inner join ibe_padron_prov_2010_m pad 
      on idm2.nombrem = pad.nomb 
      and idm2.apell1m = pad.ape1 
      and idm2.apell2m = pad.ape2 
     where idm2.codlote = 1 
      and idm2.activo = 1 
      and ((pad.ar = '2016' and pad.mes = '1') or 
       (pad.ar = '2015' and pad.mes = '7')) 
      and pad.tiden != '2'   
      and (idm2.numdocm = pad.iden || pad.liden or 
       idm2.numdocm = pad.ndocu or 
       idm2.numdocm = pad.lextr || pad.iden || pad.liden or 
       idm2.numdocm = pad.lextr || '0' || pad.iden || pad.liden or 
       idm2.numdocm = 
       pad.lextr || substr(pad.iden, 2, length(pad.iden)) || 
       pad.liden)) idm2 
    on idm3.cod = idm2.cod 

where idm3.codlote = 1 
    and idm3.activo = 1 
    and ((pad2.ar = '2016' and pad2.mes = '1') or 
     (pad2.ar = '2015' and pad2.mes = '7')) 
    and idm3.prorem = '07' 
    and ((pad2.tiden = '1' and pad2.liden is not null) or 
     (pad2.tiden = '3' and pad2.liden is not null and 
     pad2.lextr is not null)) 
    and adm2.cod is null; 
+0

未登録(pad2、pad2.mes)IN(( '' 2016 '、' 1 ')、(' 2015 '、' 7 ')) 'haveまたはより良いパフォーマンス? – sagi

+0

@sagiオラクルのオプティマイザは、両方のケースで同じクエリプランを論理的に同等に生成することが期待されます。しかし、OPが両方をテストして結果を比較することはOPにとって痛いことではない(LeketoはOPのシステムにアクセスできない)。 –

+0

私はこれを一度テストしたところ、 'IN()'は 'OR'よりも優れていることがわかりました。 @CraigYoung – sagi

2

アラーム鐘がで叫んでいます。

SELECT COUNT(idm3.cod) 

私たちはあなたのスキーマを知らないので、私たちはあなたを指摘することはできません:あなたはおそらく、あなたが唯一の重複をハッシュする行の膨大な数を生成していることがわかります、次のことを変更した場合間違い。しかし、各テーブルのPKフィールドの適切なフィルタリングをチェックすることから始めることができます。

また、Leketo's adviceに従って明示的なJOIN構文を使用することをお勧めします。結合エラーをより簡単に識別することができます。


多くの文字列番号を使用していることに気付きました。

  • 基本フィールドがchar/varcharの場合、テーブルのデザインは非効率的です。それらの列を適切な数値型に変更することで大幅に改善できます。
  • 基礎となるフィールドが既に数値タイプの場合:文字列リテラルフィルタを使用すると、おそらく索引を活用できないクエリが発生する可能性があります。正しいタイプの使用を開始すると、大幅な改善が見られるかもしれません。
+0

質問を編集しました。ありがとう! – Alex

関連する問題