0

1220200 の重複レコードが存在するテーブルがあります。

以下のクエリを使用して重複レコードを削除しています。

DELETE /*+ NO_CPU_COSTING  */
  FROM  FCST f1
  WHERE
       ROWID >
           (SELECT MIN (ROWID)
              FROM FCST f2
             WHERE 
                  f1.DMDUNIT = f2.DMDUNIT
                   AND f1.DMDGROUP = f2.DMDGROUP
                   AND f1.LOC = f2.LOC
                   AND f1.STARTDATE = f2.STARTDATE
                   AND f1.TYPE = f2.TYPE
                   AND UPPER (f1.FCSTID) = UPPER (f2.FCSTID));

これらのレコードを削除するのに約 2 分かかります。重複データをカーソルにロードして一括削除することで、一括削除アプローチも試しましたが、時間がかかります。

このコードを最適化するためのより良いアプローチは何ですか?

4

2 に答える 2

1

簡単なことは、このようなものです

delete /*+RULE*/ from t
where rowid in ( select rid
                   from ( select rowid rid,
                                 row_number() over
                                   (partition by cust_seg_nbr order by rowid) rn
                            from t
                        )
                 where rn <> 1 );

しかし、膨大なデータがある場合は

このリンクhttp://www.rampant-books.com/t_stoever_delete_duplicates.htmを確認するか、以下のコードを使用してください

 DECLARE     -- Code ©2004 by Edward Stoever
   CURSOR c_get_duplicates
   IS
      SELECT   ssrfees_term_code, ssrfees_crn, ssrfees_detl_code,
               ssrfees_ftyp_code, ssrfees_levl_code, COUNT (*)
          FROM ssrfees
        HAVING COUNT (*) > 1
      GROUP BY ssrfees_term_code,
               ssrfees_crn,
               ssrfees_detl_code,
               ssrfees_ftyp_code,
               ssrfees_levl_code;

   var_get_duplicates c_get_duplicates%ROWTYPE;

   CURSOR c_del_only_one
   IS
      SELECT ROWID
        FROM ssrfees
       WHERE ssrfees_term_code = var_get_duplicates.ssrfees_term_code
         AND ssrfees_crn = var_get_duplicates.ssrfees_crn
         AND ssrfees_detl_code = var_get_duplicates.ssrfees_detl_code
         AND NVL(ssrfees_ftyp_code,'1') = NVL(var_get_duplicates.ssrfees_ftyp_code,'1')
         AND NVL(ssrfees_levl_code,'1') = NVL(var_get_duplicates.ssrfees_levl_code,'1');

   var_del_only_one ROWID;
BEGIN
   OPEN c_get_duplicates;

   LOOP
      FETCH c_get_duplicates
       INTO var_get_duplicates;

      EXIT WHEN c_get_duplicates%NOTFOUND;

      OPEN c_del_only_one;

      FETCH c_del_only_one
       INTO var_del_only_one;

      DELETE FROM ssrfees
            WHERE ROWID = var_del_only_one;

      COMMIT;

      CLOSE c_del_only_one;
   END LOOP;

   CLOSE c_get_duplicates;
END;
/
于 2013-06-17T09:24:49.017 に答える
0

「ROWID > ...」を含むクエリは、基本的に疑わしいものです。

あなたが探しているのはこれだと思います:

DELETE FROM
  FCST f1
WHERE
  ROWID NOT IN (
    SELECT   MIN(ROWID)
    FROM     FCST f2
    GROUP BY f2.DMDUNIT,
             f2.DMDGROUP,
             f2.LOC,
             f2.STARTDATE,
             f2.TYPE,
             UPPER(f2.FCSTID));

サブクエリは、GROUP BY 句の列のすべての一意の値をカバーする一連の ROWID を識別し、その他はすべて削除されます。

保持する行だけを含む新しいテーブルを作成する方が高速な代替手段かもしれませんが、これで十分なパフォーマンスが得られる場合は、これを使用してください。

于 2013-06-17T10:02:07.490 に答える