最初のページに戻ります。

総合の目次があるページに戻ります。

よく使うマニュアルです

Wiki

updated on 2004.06.23

a.14. 2000年問題 其の拾肆

[ Previous ] [ HOME ] [ Upper ] [ Next ]


エラーがでた

「その13」の翌日、会社に言ったら、MSGWで止まっている。はら?何だろう。あれ?このファイル、おかしいぞ?あー、これ、オンライン・バックアップファイルだ。だれか、テストで、古いデータを新しいレコード様式にFMTOPT(*NOCHK)でコピーしたな。そうだ、CLPもFMTOPT(*NOCHK)は要注意だな。レコード様式が、ファイルの枠組みにすぎないことを、身をもって知る瞬間。まあ、これは数字検査で何とかなるな。どうもTESTNは検査が甘いような気がする。

SRCDATがまた出てる。そういえば、このフィールドどうなるのだろう?日付の大小検索(SEU)は2000年後でもきちんとできるのかな?でないと、困るけど。まあ、検索だけなので、8桁にしなくても、内部で判定してくれればいいのだけど。

ま、それよりも問題は、そのエラーが出ていた時間。朝8時だった。しかも、まだやろうとしている。これは、遅い!なんとかしなくては。

出力する結果ファイル

このツールを実行すると、ファイル名+ファイルライブラリー名+レコード様式名+フィールド名+日付コードをキーとしたファイルが出来る。後先考えず作ってしまい、更新+追加になっている。つまり、レコードを一件読み込んでは、その全フィールドを順次データ検査したいた。上記のファイルでは、どうしても、キーにフィールド名があるために、2件目を読み込んだ結果を、更新して、ヒット件数をセットしなくてはならない。データにより、同じフィールド名でも、違う日付コードがあり得る。

最終目的は以下の通り。

ファイル名 ファイルライブラリー名 レコード様式名 フィールド名 日付コード ヒット回数 全体の件数 割合
FILEA XXXDBF RCDXXX FLD001 YMD 100 5,000 2%
        YYMD 500 5,000 10%
        *OTHR 4,400 5,000 88%
      FLD002 YY 4,100 5,000 82%
        *ZERO 900 5,000 18%

FLD001はYMDが2%で、YYMDが10%、日付以外は88%という結果から、YMD、YYMDは偶然、日付形式のデータだったのだ、と判断する。

FLD002はYY(西暦4桁)が82%で,900レコードにゼロが入っていた。たぶん、日付の年だろう。なにか未使用の場合、0で、使われていると年数字らしい。

と、こんな感じになる。

レコード一件単位に、全フィールド検査?フィールド一件単位に、全レコード検査?

ここが、遅くなる第一の関門だ。そこで、日付コードは全部で10個そこそこなのを利用して、その集計件数を配列にセットして、フィールド単位に、件数集計を出力する事にした。つまり、1フィールド単位に、対象レコードを全部読み込み、EOFで、データを書き出し、次のフィールドへ。これならば、結果ファイルは、出力専用だ。これで出力バッファも取られて、SEQONLYとなる。まず間違いなく、早くなるだろう。

日付コード

また、日付コードに、日付の表意コード以外も含めた。

  • *ZERO=該当フィールドが0となっていて判断できない。日付かもしれないし、そうでないかもしれない。
  • *ERR=データのエラー。(符号エリアのみ参照した。本来は出ないはず。よって、これは、数値符号エラー)。
  • *MINUS=マイナスの数値(日付ではあり得ない)。
  • *OTHR=日付以外のデータ。

順次だけでいいのか

いままでは、相対レコード番号の1番目から、順次に、1000件読み込んできた。この部分も、考え直した。つまり、もし、200万件あっても、最初の1000件だけでは、残りの199万9000件を無視することになる。これで、日付判定するのには、あまりに不安だ。そもそも、日付を統計的な確率で出そうとするなら、もっと、サンプリングの幅を持たせねば。どうやろうか。乱数はないし。(ILEはAPIで乱数関数をサポートしているようです。しかし、今更、もう時間も無い。)

そこで、全体の件数の1%を、取り出して、その回数分、相対レコード番号にアクセスする。そして、全体の件数÷回数で、相対レコード番号の間隔を求めて、まんべんなくレコードを抜き出す事にした。たとえば、全体が100000レコードならば、100レコード単位に1000回アクセスしてレコードを取り出す。中には、削除レコードもあり、欠番の相対レコード番号もあるだろうが、面倒なのでもう無視。どのみち、検索件数も分かるので、いいだろう。少なすぎたら、やり直すのさ。

RCDNBR	MULT	0.01	CHAINS
RCDNBR	DIV	CHAINS	ADDS         
1	DO	RCDNBR	RRN
RRN	CHAIN	FAILE
	...        
	END	ADDS        

として、RCDNBRがレコード件数、CHAINSがアクセス回数。ADDSに増分値をセットした。ところが、

一件も、読まないファイルがある

データは1000件入っている。かなり古いデータだ。ああ、件数は1000件でも、削除されて、頭1500件がなく、相対レコード番号が1501からなっている。100回、10単位に読み込んでも、1000までなので、すべて、空振り。これは、1から最大件数のDOループにしたのが、誤り。開始行番号から最終行番号までのDOにしなくてはいけなかった。この値で、RRNでCHAINするので。

無限ループした

ADDSが0だったのだ。要は計算結果のADDSが0となっていたのだ。みなさん、ご存じだったろうか。END     0 と入れると、SEUでエラーになる。しかし、変数フィールドを入力した場合、ここが0だと、当然、増分値0なので、カウントアップしないのだ。ADDSが0ならば1にするようにした。また、上記CHAINSも分母になるので、CHAINSが0ならば、総件数(この件数が小さすぎるので、0になるのだ)をセットするようにした。エラーはこれくらいだった。

でも、実行すると、やっぱり、遅い。たぶん、出力ファイル専用にした時点ではやくなっているはずだが、ランダムアクセスで足を引っ張るのだろう。仕方ないので、アクセス回数の最大値を1000回に制限した。

さらに、欲が

結果を見る限り、結構信頼性の高いデータだ。これは、移行後の内容検査にも使えるぞ、それなら、最初の、順次読み込みも、パラメータで出来ないだろうか。勿論、前のプログラムのソースはあるので、移植して、ランダムとシーケンシャルの両方出来るようにした。ポイントは、シーケンシャルの場合のSEQONLYを確保したいので、RNDFとSEQFの2つをF仕様書に設定した。プログラム内部記述の場合は、READやCHAINの結果のフィールドにデータ構造を指定できるので、同じデータ構造で、兼用できるので、ロジックが簡潔になった。

どっちが(ちょっと)得か、よーく考えてみよう

パラメータで、2つのロジックを制御する場合、どっちがいいだろうか。

1	DO	MAXFLD
PARM	IFEQ	'R'
	EXSR	@RNDD
	ELSE
	EXSR	@SEQD
	ENDIF
	ENDDO        

MAXFLDは、フィールド数です。このフィールドの数分、@RNDDと@SEQDの中で、さらに、レコードアクセスのループが入ってる。

これと、

PARM	IFEQ	'R'
1	DO	MAXLFD
	EXSR	@RNDD
	ENDDO
	ELSE
1	DO	MAXFLD
	EXSR	@SEQD
	ENDDO
	ENDIF          

どちらがいいでしょう。

どちらも、結果は同じですが、DOループの中で、何回もIF判断をするより、プログラムで最初に一度、IF判断をしたら、DOループに入って、IFない方が、まあ、効率は良さそうです。そこで、あえて、コードは無駄ですが、後者を選びました。これに併せて、コマンドも*SEQでシーケンシャル、*RNDでランダムアクセスのサンプリング方式の指定を出来るようにした。

さて、夜も更けたので、夜9時にSBMJOBして帰宅。投入したのは、あの、オブジェクトリストAPIから、物理ファイルだけ抜きだし、上のツールを呼び出す奴だ。

と、ここまでが、昨日のお話。

さて、一夜あけて、今日の結果は、午前6時に終了していました。早くなっている。まあ、アクセス回数にリミットをつけたのもよかったのだろう。さて、結果は、上々だ。でも、*OTHRとか、*MINSとかの無駄なデータが多い。それに、偶然気づいたが、EXCEL用のダウンロードデータに「98/01/10」が、スラッシュつきで、文字で入っている。こうしないと、EXCELは日付と認めないので仕方ないが、まあしょうがない。スラッシュがあったら、日付コードを*DAT?としよう。最後に?をつけたのは、これ以外に/を使っているデータがあるからだ。

ほかにも、マイナスだったら、もう判断するのは、資源の無駄なので、したくない。今日は、一日このツールのエンハンスにかかりっきりだった。本番移行後に役だってほしいな。今日やった内容も、書きたいけど、この後の詳しい内容は、後日。今日は、もう店じまい!

ここでは、結果ファイルのDDSを載せます。また変わるかも。

     A*------------------------------------*
     A          R RTVY2KR
     A*------------------------------------*
     A            A2FILE        10          COLHDG('FILE名')
     A            A2LIB         10          COLHDG('LIB名')
     A            A2RCD         10          COLHDG('RCD名')
     A            A2FLD         10          COLHDG('FLD名')
     A            A2FMT          5          COLHDG('DATE FMT')
     A            A2FLDA         1          COLHDG('FIELD ATTR.')
     A            A2FLDL         3  0       COLHDG('FIELD LENGTH')
     A            A2DEGT         3  0       COLHDG('FIELD DIGITS')
     A*
     A            A2CNT          7  0       COLHDG('COUNTS')
     A            A2NZRO         7  0       COLHDG('0でないカウント')
     A            A2TOL          7  0       COLHDG('合計')
     A*
     A            A2NONE         1          COLHDG('0件データ')
     A            A2SKIP         1          COLHDG('無視')
     A*
     A            A2CHD1        20          COLHDG('COLHDG1')
     A            A2CHD2        20          COLHDG('COLHDG2')
     A            A2CHD3        20          COLHDG('COLHDG3')
     A            A2TXT         50          COLHDG('TEXT')
     A*
     A          K A2FILE
     A          K A2LIB
     A          K A2RCD
     A          K A2FLD
     A          K A2FMT        

続く...


[ Previous ] [ HOME ] [ Upper ] [ Next ]

You are at K's tips-n-kicks of AS/400

 

Ads by TOK2