1

MS SQL Server、MySQL、および Oracle をサポートするアプリには、次の関連する列を含むテーブルがあります (ここに示されている型は Oracle のものです)。

ShortText VARCHAR2(1700) indexed
LongText CLOB

アプリは、850 文字以下の値を ShortText に格納し、それより長い値を LongText に格納します。そのデータがどの列にあるかに関係なく、そのデータを返すビューを作成する必要があります。これは、SQL Server と MySQL で機能します。

SELECT
  CASE
    WHEN ShortText IS NOT NULL THEN ShortText
    ELSE LongText
  END AS TheValue
FROM MyTable

ただし、Oracle では、次のエラーが生成されます。

ORA-00932: inconsistent datatypes: expected CHAR got CLOB 

...つまり、Oracle は 2 つの列を暗黙的に同じ型に変換しないため、クエリで明示的に変換する必要があります。データが切り捨てられたくないので、使用する型は CLOB と同じ量のデータを保持できる必要があります。これは、(Oracle の専門家ではない) 私が理解しているように、CLOB のみを意味し、他に選択肢はありません。

これはOracleで機能します:

SELECT
  CASE
    WHEN ShortText IS NOT NULL THEN TO_CLOB(ShortText)
    ELSE LongText
  END AS TheValue
FROM MyTable

しかし、パフォーマンスは驚くほどひどいです。LongText を直接返すクエリでは、約 9,000 行で 70 ~ 80 ミリ秒かかりましたが、上記の構成では 30 ~ 60秒かかり、許容できません。

そう:

  1. CLOBと同じ量のデータを保持できる、両方の列を強制できる他のOracleタイプはありますか? 理想的には、MySQL の LONGTEXT や SQL Server の NTEXT (または NVARCHAR(MAX)) のような、よりテキスト指向のものでしょうか?
  2. 私が見るべき他のアプローチはありますか?

いくつかの詳細、特に @Guido Leenders によって要求されたもの:

Oracle バージョン: Oracle データベース 11g 11.2.0.1.0 64 ビット プロダクション
私が唯一のユーザーかどうかは定かではありませんが、相対的な時間は依然として印象的です.

以前に投稿したパフォーマンスを見た小さなテーブルの統計:
  行数: 9,237
  varchar 列の全長: 148,516
  clob 列の全長: 227,020
4

1 に答える 1

1

to_clob はかなり高価なので、避けるようにしてください。しかし、9,000 行では妥当なパフォーマンスが得られるはずです。同様のデータモデルの動作を持つ、開発したアプリケーションの 1 つに基づく次のテスト ケース:

create table bubs_projecten_sample
( id number
, toelichting varchar2(1700)
, toelichting_l clob
)

begin
  for i in 1..10000
  loop
    insert into bubs_projecten_sample
    ( id
    , toelichting
    , toelichting_l
    )
    values
    ( i
    , case when mod(i, 2) = 0 then 'short' else null end
    , case when mod(i, 2) = 0 then rpad('long', i, '*') else null end
    )
    ;
  end loop;
  commit;
end;

ここで、キャッシュ内のすべてとダーティ ブロックが書き出されていることを確認します。

select *
from   bubs_projecten_sample

テスト性能:

create table bubs_projecten_flat
as
select id
,      to_clob(toelichting) toelichting_any
from   bubs_projecten_sample
where  toelichting is not null
union all
select id
,      toelichting_l
from   bubs_projecten_sample
where  toelichting_l is not null

テーブルの作成は、データの書き込み、17K の一貫性のある取得、4K の物理読み取りを含め、通常のエントリ レベルのサーバーで 1 秒もかかりません。ディスク (rpad に注意) に格納されるのは、toelichting の場合は 25K、toelichting_l の場合は 16M です。

問題についてさらに詳しく説明していただけますか?

大きな CLOB がインラインで格納されていないことを確認してください。通常、大きな CLOB は、別のシステム管理テーブルに格納されます。テーブル内に大きな CLOB を格納すると、フル テーブル スキャンを使用してテーブルを処理するコストが高くなる可能性があります。

また、常に両方の列にデータを入力することも想像できます。最初の非常に多くの文字に対して機能するインデックス作成の利点はまだあります。CLOB または shortText 列が先行しているかどうかを示す指標を使用して、テーブルに記憶する必要があるだけです。

補足として; 850 と 1700 には違いがあります。それらを等しくすることをお勧めしますが、文字セマンティクスを使用してテーブルを作成していることを確認することを忘れないでください。これは、"varchar2(850 char)" を使用してステートメント レベルで実行できます。Oracle は実際には 850 * 4 バイトに適合する列を作成することに注意してください (少なくとも AL32UTF8 では、「32」は「1 文字あたり最大 4 バイト」を表します)。幸運を!

于 2013-11-25T07:26:59.467 に答える