0

次のような繰り返し値の複数の計算を回避することで、このクエリのパフォーマンスを向上させる方法はありますか

regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM| TO |.csv|\d+:\d{2}:\d{2}', '')
? と

to_date(regexp_replace(regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', ''), '^(\d{4}- \d+-\d+)_.+$', '\1'), 'YYYY-MM-DD')

この列は 3 回と 2 回計算され、いくつかのテストを実行しましたが、date_start 列を削除するだけで、クエリのパフォーマンスが約 20 秒向上しました。オラクルが値を保持し、複数の計算を回避するためのより良い方法を提供するかどうかは素晴らしいことだと思います。また、私は避けたいと思います

実際のクエリ:

選択する *
から (
  選択する
      row_number() 以上 (DCRAINTERNALNUMBER, ISSUE_DATE, PERMIT_ID による分割 to_date(regexp_replace(regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}) による順序) , ''), '^.+_(\d{4}-\d+-\d+)_$', '\1'), 'YYYY-MM-DD') desc) as row_order,
      to_date(regexp_replace(regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', ''), '^(\d{4}- \d+-\d+)_.+$', '\1'), 'YYYY-MM-DD') を date_start として、
      to_date(regexp_replace(regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', ''), '^.+_(\d{ 4}-\d+-\d+)_$', '\1'), 'YYYY-MM-DD') を date_end として、
      temp2.​​
  schema.TABLE_NAME temp2 から
) t

また、複数の計算を避けるためにこのようなものをシミュレートしようとしましたが、すべてのネストされた select ステートメントのために何も改善されません...クエリが約 25 秒遅くなります。

選択する *
から (
  row_order として (DCRAINTERNALNUMBER、ISSUE_DATE、PERMIT_ID 順、date_end desc によるパーティション) で row_number() を選択し、
  temp1.*
  から (
      to_date(regexp_replace(date_raw, '^(\d{4}-\d+-\d+)_.+$', '\1'), 'YYYY-MM-DD') を date_start として選択し、
          to_date(regexp_replace(date_raw, '^.+_(\d{4}-\d+-\d+)_$', '\1'), 'YYYY-MM-DD') as date_end,
      temp2.​​
      から (
      regexp_replace(my_source_file, 'TABLE_NAME_|_AM|_PM|_TO_|\.csv|\d+:\d{2}:\d{2}', '') を date_raw として選択し、
        temp3.*
        schema.TABLE_NAME temp3 から
      ) 温度2

  ) 温度1
) t

4

3 に答える 3

2

これが入力値がほとんどない決定論的な PL/SQL 関数である場合は、次のように変更してみます。

select expensive_function(some_value)
from   large_table;

... に ...

select (select expensive_function(some_value) from dual)
from   large_table;

... Oracleにはそのためのキャッシュメカニズムがあるためです。SQL式をサブクエリにプッシュするだけで試してみてください。それが機能しない場合(または機能する場合でも)、そのSQLコードをPL/SQL関数に移動して試してみます。

もちろん、11g を使用している場合は、pl/sql 関数のキャッシュを直接使用します: http://www.oracle.com/technetwork/issue-archive/2007/07-sep/o57asktom-101814.html

于 2013-05-13T13:09:37.157 に答える
1

関数の呼び出し回数を減らすことに関する特定の質問には答えませんが、regexp_replace 関数を複数回呼び出すのではなく、regexp_substr を使用することを検討しましたか? これにより、作業が少なくなり、高速になるはずです。また、データが完全に一致しない場合 (たとえば、ファイル名が .csv ではなく .txt の場合) に例外が発生する可能性も低くなります。

何かのようなもの...

select * 
from (
  select row_number() over (partition by DCRAINTERNALNUMBER, ISSUE_DATE, PERMIT_ID order by to_date(regexp_substr(my_source_file,'\d{4}-\d{1,2}-\d{1,2}'),'yyyy-mm-dd') desc) as row_order,
  to_date(regexp_substr(my_source_file,'\d{4}-\d{1,2}-\d{1,2}'),'yyyy-mm-dd') as date_start,
  to_date(regexp_substr(my_source_file,'\d{4}-\d{1,2}-\d{1,2}',1,2),'yyyy-mm-dd') as date_end,
  temp2.* 
from schema.TABLE_NAME temp2) t

あなたのデータを適切に解釈した場合

TABLE_NAME_2011-3-1_11:00:00_AM_TO_2013-4-24_12:00:00_AM.csv

この 2011 年 3 月 1 日が開始日で、2013 年 4 月 24 日が終了日です。同じパターン マッチングを使用してこれらを日付に取得できますが、開始日の最初のインスタンス (これが既定であるためパラメーターは必要ありません) と終了日の 2 番目のインスタンス (これには追加の ,1,2 が必要です) を選択しますsubstr を先頭 (文字 1) から開始し、2 番目のインスタンスを選択します。

それが役立つことを願っています。

于 2013-05-13T13:01:30.810 に答える