2ntブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

十分なページ・サイズを持つ SYSTEM TEMPORARY 表スペースが存在しません。

こんばんわ、ふぃぶです。

さて、今日は表題のお話です。
この憎き表題のお話です。

DB2でSELECT文組んでるときにこのエラー出ることがたまにありました。



ERROR [54048] [IBM][CLI Driver][DB2/NT] SQL1585N 十分なページ・サイズを持つ SYSTEM TEMPORARY 表スペースが存在しません。SQLSTATE=54048


DB2に明るくないあたしのような人間には「なんのこっちゃぁ!」って感じです。
エラー情報なんかで検索するとまず有力そうな情報があるのは次のサイトさんのページです。

参考サイト様


今回さらっと読んでたんですが余り意味を理解していませんでした。
SYSTEM TEMPORARYテーブルってののページサイズが足りないのね。くらいの認識です。
いわゆる一般で言う「一時表」のサイズが足りないそうです。
まぁそのとおりなんですけど・・・。

では一体何が原因だったのかを書いていきます

【事例】
今回あたしは次のようなSELECT文を作成していました。


SELECT
A.COLUMN_1
,A.COLUMN_2
,A.COLUMN_3
~以下続く~
,A.COLUMN_29
,A.COLUMN_30
FROM HOGE_TABLE A
INNER JOIN HOGE_2_TABLE B
ON A.COLUMN1 = B.COLUMN
~以下結合~
ORDER BY A.COLUMN_1


ざっくりとこんな感じです。
発行すると先に述べたエラーが発生します。

上記の参考サイト様では、ソートで食いつぶしてる事例がかかれているため
とりあえずあたしもORDER BYを外してみましたが、エラーは出続けます。

一体何!?って思ったらですね、列数が多かったみたいです。

今回扱ってるシステムではSYSTEM TEMPORARYは1つしか作成されていません。
用意されているSYSTEM TEMPORARYのページサイズは4Kとなっていました。
※ db2 list tablespace show detail というコマンドで確認できます

で、SELECT文の取得項目に今回たくさんデータを指定しているわけですが、
どうもコレの合計サイズが4Kを超えたみたいです。

例えばCOLUMN_1~COLUMN30はそれぞれVARCHAR(256)で定義されているとします。
そうするとこれらを全て取得すると7680Byteの領域を必要としますね。
SYSTEM TEMPORARYは4K、つまり4096Byteなので思いっきり超過しています。

SYSTEM TEMPORARYは4Kと定義されている場合、
4K以上の作業領域が必要なものにはそもそも使われないらしいです。
ので↑以外のテンポラリーテーブルは存在しないので、SQL結果の作業スペースがまったくなくなり
エラーするっぽい。

現に、SELECTで取得する項目をCOLUMN1~15に減らすとエラーは起きず実行結果が帰ってきました。
(VARCHAR(256)* 15 = 3840Byteなので足りてる)


ということっぽい。
これの恒久的な対応としてはSELECTの取得項目をSYSTEM TEMPORARY以下に収めるか
またはページサイズがもっと大きいSYSTEM TEMPORARYを作成するかの2つになりそうです。

またやってみたところ、4Kのテンポラリと8Kのテンポラリが定義されていた場合、
SELECTで4K超えた場合8Kのほうをちゃんと使ってくれるっぽいです。
8Kのほうが使われているかどうかは8Kのほうに定義してあるコンテナーのパス配下に
一時ファイルが作成されているかどうかで多分判断できます。


てんぽらりの作り方も機会があれば書きたいなぁ・・・
でわでわ

[DB2]DB2のUDF作成で困ったり困りまくったり

こんにちは、ふぃぶです。

最近はDB2なんぞを扱ってます。
これがまた色々曲者なんですが、今詰まってるのがUDF作成です。

DB2にはUDF(ユーザ定義関数)という機能が付いてます。
TO_DATEとかSUMとかSQL関数を自分で定義できるようなもので
ユーザはこれを定義することによってSQL内で関数として使用できます。
イメージ的にはプロシージャと同じようなもんだと思っていいと思いますよ。

今回扱ってるDB2は9.5。PL/SQLをサポートしていないようなのでOracleのPL/SQLは
そのまま使えなかったり。
※DB2がPL/SQLサポートしだしたのは9.7からっぽい。
のでお作法に習い、以下のようにUDFを定義します。



CREATE FUNCTION GET_CD_VALUE( SEARCH_VAL VARCHAR(100) )
RETRUNS VARCHAR(100)
LANGUAGE SQL
BEGIN ATOMIC
DECLARE ret_string VARCHAR(100) DEFAULT '';
FOR cur AS SELECT CD_NM
FROM MS_CD
WHERE CD_VAL LIKE '%' || SEARCH_VAL || '%'
FETCH FIRST 1 ROW ONLY
DO
SET ret_string = CD_NM;
END FOR

RETURN ret_string;

END


これで実行するとLIKE文のところでエラーになります。
なんでなんだろう・・・
ちなみにWHERE句の部分を
WHERE CD_VAL LIKE SEARCH_VAL
にしてもエラー。 
WHERE CD_VAL LIKE 'AAA'
とかにしたら通る。
WHERE CD_VAL = SEARCH_VAL
にしても通る。
パラメータ変数をLIKEで使えてない感じ?
もう原因がわかんなくて死にそうです・・・。

解決方法求む、次回解決変になるといいな。
でわでわ。