OracleでCLOBに高速アクセスする方法

ちょっと釣りみたいなタイトルです。

LOBに関してはOracleが分厚いPDFファイルを用意しているので、そちらを参照して理解するのが良いと思います。今回はCLOBへアクセスする速度が速くなるわけではなく、いかにCLOBへアクセスさせないようにする方法です。アクセス速度自体はchunkのサイズとか気にすれば良いと思います。

そもそもなぜCLOBを使うのか?

これはVARCHAR2が4000バイトまでのため、AL32UTF8のデータベースの場合、日本語は最大4バイト消費します。(マニュアルによると、4バイトのUTF8は内部で6バイト使うみたいな事が書いてありましたので、ちょっと検証する必要はありそうです。)
ちなみに全角文字が2バイトという神話はSJISやEUC(一部3バイトですが)の時代の話です。UTF8では半角カナや漢字は3バイト、一部の漢字は4バイト使います。

さて、CLOBに入れるデータは常に4000バイト以上とは限りません。4000バイトで収まる場合はVARCHAR2のカラムに入れて収まらない場合はCLOBのデータに入れれば良いと思います。つまり1000バイトの文字列であればCLOBに入れる必要は無いわけです。今回はぱぱっと対応する策(松竹梅で言う梅コース)でどれほど効果があるか確認してみました。

COMMENT_TEXTがCLOBの列です。梅コースのためVARCHAR2の列はありません。LENGTH関数はCLOBに対しては文字数を返します。(LENGTHBはCLOBには適用できません)。CLOB中にはマルチバイト文字が2バイトで入っているという噂なので(UCS2で保存してるの??) 2000で判定しています。(サロゲート文字については未検証)。TO_CHARでVARCHAR2に変換しています。

SELECT
    CASE
        WHEN LENGTH(COMMENT_TEXT) > 2000 THEN NULL
        ELSE TO_CHAR(COMMENT_TEXT)
    END AS COMMENT_TEXT_A,
    CASE
        WHEN LENGTH(COMMENT_TEXT) > 2000 THEN COMMENT_TEXT
        ELSE NULL
    END AS COMMENT_TEXT_B
FROM DIARY_COMMENT

上記のSQLを実行すると1014レコード帰ってきます。
全部CLOBとして取得する場合は3120msかかりますが、上記のSQLでは125ms程度になりました。
※CLOBとしては2レコードしかありませんでした

ものによりますが、4000バイト以上使う割合が少ないものではこういうやり方もありなのではないかと思います。

最速はおそらくVARCHAR2(4000)の列をいくつか作って分割するという方法とかあると思います。設計が美しくないですけど。。。

新しいサイトもよろしくお願いします!