1

以下にまとめたクエリがありますが、実行はひどいものです (ご覧のとおり)。

昨日のデータを参照できるように日時を変換する方法に関係していると確信しています。

dtInteractionLocalStartTime は日時フィールドであり、yyyy-mm-dd hh:mm:ss.sss ではなく mm/dd/yyyy として表示したい

これを最適化する方法についてのアイデアはありますか? 過去2日間過ごしましたが、わかりません。

これが私のクエリです:

SELECT TOP 100 PERCENT
       Date ,
       CONVERT(varchar, VDN) AS VDN ,
       COUNT(*) AS Calls ,
       Avaya
FROM ( SELECT DISTINCT TOP 100 PERCENT
              CONVERT(varchar,dtInteractionLocalStartTime,101) AS Date ,
              vcVectorNumber AS VDN ,
              iCompoundID ,
              'CM03' AS Avaya
       FROM NICEHUB3ADTM.nice_dw.dbo.vwNiceDBKitInteraction AS i
       WHERE CONVERT(varchar(10) , dtInteractionLocalStartTime,101) = CONVERT(varchar(10),GETDATE()-1,101)
         AND iMediaTypesId = 2
         AND tiCallDirectionTypeID = 1
         AND tiInteractionTypeID = 2
         AND iInteractionOpenReasonID & 16 = 0
         AND iInteractionOpenReasonID & 4 = 0
         AND iInteractionID NOT IN ( SELECT iInteractionID
                                     FROM NICEHUB3ADTM.nice_dw.dbo.vwException AS e
                                     WHERE i.iInteractionID = iInteractionID
                                       AND iExceptionTypeID IN (37, 12, 12310)
                                   )
     ) AS derivedtbl_1
GROUP BY Date ,
         CONVERT(varchar,VDN) ,
         Avaya
ORDER BY Date ,
         VDN
4

2 に答える 2

4

いくつかの考え(「ひどく実行される」はあまり良い問題ステートメントではないため):

  • 全面的に、を取り除きtop 100 percentます。これは、すべてを返すことを意味します。これは、SQL がデフォルトで行うことです。

  • の使い方はselect distinctコードです。これは、間違った質問をしている、または間違った質問をしている、またはクエリに含まれるエンティティ間の関係のカーディナリティを理解していないことを強く示しています。SQL はセットを扱います。セットは定義上、一意であるため、一意性を強制する必要がある場合は、ほぼ間違いなく何か間違ったことをしています。

  • 派生テーブルは必要ありません

  • 同じ列に対して 2 つのビット操作テストを実行しています。を組み合わせることができます。

  • 相関サブクエリを実行していて、not in (...)ではなく使用していますnot exists (...)

  • vcVectorNumber を varchar に変換しています。そのデータ型がわからないのは無関係のようです。アプリケーションに文字列への変換を処理させてください。

  • datetime列を比較しながら変換します。それは式に変わり、式はインデックスを使用できないため、クエリオプティマイザーが適切なインデックスを使用できないようにします。そうしないでください。datetime可能であれば、そのような飛び回る必要のない方法で列をテストしbetweenてください。

これは、クエリをリファクタリングする方法です。これで同じ結果が得られると思います:

select convert(date,i.dtInteractionLocalStartTime) as Date  ,
       i.vcVectorNumber                            as VDN   ,
       count(distinct i.iCompoundId)               as Calls ,
       'CM03'                                      as Avaya
from NICEHUB3ADTM.nice_dw.dbo.vwNiceDBKitInteraction i
where i.dtInteractionLocalStartTime between dateadd(day ,-1 ,convert(datetime,convert(date,getdate()))) -- yesterday, midnight/start-of-day
                                        and dateadd(ms  ,-3 ,convert(datetime,convert(date,getdate()))) -- yesterday, end-of-day
  and i.iMediaTypesId                     = 2
  and i.tiCallDirectionTypeID             = 1
  and i.tiInteractionTypeID               = 2
  and i.iInteractionOpenReasonId & 0x0014 = 0 -- ( 16|4 is 20, 0x0014)
  and not exists ( select *
                   from NICEHUB3ADTM.nice_dw.dbo.vwException e
                   where e.iInteractionID = i.iInteractionID
                     and e.iExceptionTypeID IN ( 37 , 12 , 12310 )
                 )
group by convert(date,i.dtInteractionLocalStartTime) ,
         i.vcVectorNumber
order by convert(date,i.dtInteractionLocalStartTime) ,
         i.vcVectorNumber

最後に、4 つの部分からなるテーブル名は、クロスサーバー クエリまたはリンク サーバーの使用の可能性を示しています。もしそうなら(そして私の経験では)、それは高価な操作になる可能性があります。最初にリモート データをローカルの一時テーブルに吸い込むと、パフォーマンスが向上します。

于 2013-08-08T22:52:24.083 に答える