4

バイナリレベルでOracleにデータを保存するタイプまたは方法はありますか。表のdmlとpl/sqlの両方の操作に興味があります。

現在、すべてのバイナリ要素はvarchar2(1000)= '11111 ... 0000.1111'として格納されていますが、操作とデータストレージサイズがかなり大きいため、最適化のためのいくつかのソリューションが必要です。このデータをバイナリ形式で保存できる場合は、1000/8バイトが必要になります(700mlnを超えるレコードがあります)

おそらく解決策は、これらの操作に何らかのjava+oracleの組み合わせを使用することです。

アイデアや提案を歓迎します。

4

5 に答える 5

8

最大 4000 バイトのバイナリ データを格納する場合は、 RAWデータ型を使用します。データは、文字セット変換なしでバイトの文字列として格納されます。

UTL_RAWパッケージを使用して で操作を実行しRAWsます。

LONG RAW データ型は非推奨です。4000 バイトを超えるデータを操作する必要がある場合は、 BLOBに切り替える必要があります。

于 2012-06-25T13:47:44.517 に答える
7

Vincent Malgrat の回答を参照してください。バイナリ データを Oracle に格納して処理する場合は、RAWデータ型が最適です。

(アレゲンの答えが暗示しているように、データベースで「処理」する必要のない画像、ビデオ、オーディオ、または圧縮データを保存および取得することを意図している場合、それを「保存」して「取得」しているだけですの場合、BLOBデータ型の方が適切な場合があります。

(注: RAW データ型は 4000 バイトに制限されていますが、BLOB データ型はそうではありません。パフォーマンス上の理由から、定期的に値. 多くのクエリがバイナリデータを参照していない、はるかに長い値の場合、私はBLOB. 、ブロックに収まる行数など)RAWBLOB

あなたが提供した情報から、あなたが説明した特定の問題については、RAW行くべき道のように聞こえます。1000 ビットのシーケンスがあることを指定しますが、それが定数なのか最大長なのか、またはバイナリ データの長い文字列を列に収まるより管理しやすいチャンクに分割したのかどうかはまったく明確ではありません。(実際にバイナリ データの単一の巨大なチャンクを操作している場合は、それを小さな断片の束に「切り刻む」ことや、各断片を別々の行に格納することは避けたいと考えています。すべてを単一の BLOB としてまとめて保存し、単純なストリームとして操作します。

これらすべてが、BLOB と RAW のどちらを使用するかの決定に実際に役立ちます。


それはさておき、1 と 0 の VARCHAR2 表現 (たとえば、「00101010」、実際の情報の各「ビット」が個別の文字として格納され、より効率的に格納されたバイナリ表現、各「8 ビット」 " 1 バイトのストレージを必要とする実情報の...

OracleRAWデータ型では、8 ビットが 1 バイトに格納されます。つまり、RAW(125) は VARCHAR2(1000) に相当するものを格納し、1 行あたり 875 バイト節約できます (SBCS の場合、DBCS を使用している場合の 2 倍以上)。これにより、ストレージ要件が大幅に削減され、ブロック内の行数が増え、パフォーマンスが向上する可能性があります。

現在1と0の文字列として保存されているデータを変換するためにVARCHAR2、それを行う組み込み関数を知りません。しかし、バイナリ文字列表現を 16 進文字列表現に変換する独自の関数をロールするのはかなり簡単です。その後、組み込みHEXTORAW関数を使用して に変換できますRAW

出発点として使用できる例を次に示します。

(注: この関数は単なる例です。入力文字列の長さが 8 文字の倍数でない場合は効果的に処理されません。また、'1' または '0' 以外の文字を含む文字列値での動作です。適切ではないかもしれません(書かれているように、「0」以外の文字は「1」であるかのように扱われます。しかし、出発点としては十分です)。

create or replace function binstr_to_hexstr
( as_binstr in varchar2 ) return varchar2
is
  li_n binary_integer default 0;
  ls_hexstr varchar2(16) default '0123456789ABCDEF';
  ls_return varchar2(2000) default '';
begin
  if ( as_binstr is null ) then
    return null;
  end if;
  ls_return := '';
  li_n := 0;
  for i in 1 .. length(as_binstr) loop
    li_n := li_n*2 + abs(instr('01',substr(as_binstr,i,1))-1);
    if mod(i,4) = 0 then
      ls_return := ls_return || substr(ls_hexstr,li_n+1,1);
      li_n := 0;
    end if;
  end loop;
return ls_return;
end;
/

SELECT binstr_to_hexstr('00101010') AS hexstr FROM DUAL UNION ALL
SELECT binstr_to_hexstr('00x0 010') FROM DUAL;

HEXSTR                                                                             
------
2A
2A

注: この関数は、入力文字列の長さが 8 の偶数倍 (つまりMOD(length(as_binstr),8) = 0) の場合にのみ、期待される結果 (一致する 16 進表現) を返します。それ以外の場合、関数は末尾のビットを「失う」か、奇数の 16 進数を返します。(関数は、入力引数の長さが 8 の倍数でない場合に例外をスローするように変更できます。)

HEXTORAWおよびRAWTOHEX関数は、TOAD、SQL Developer、SQL*Plus などのクライアント アプリケーションを使用してデータを操作する場合に便利ですRAW。(HEXTORAW関数は、関数からの出力を RAW に変換するために使用するものbinstr_to_hexstrです。)例として:

create or replace function binstr_to_raw
( as_binstr in varchar2 ) return raw
is
begin
  return hextoraw(binstr_to_hexstr(as_binstr));
end;
/

Vincent Malgrat が彼の回答で指摘したように、Oracle はRAW データの操作に役立ついくつかのパッケージ (UTL_RAWおよび など) を提供しています。UTL_ENCODE

http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/u_raw.htm

于 2012-06-28T15:42:38.970 に答える
2

BLOBこれには、 (Binary Large OBject) タイプを使用できます。使用例へのリンク。

于 2012-06-25T11:19:56.567 に答える
2

今日の時点で、私はこれを 10 および 11g で使用していましたが、答えを更新する必要があると思います。これらの種類のデータの組み込みデータ型は( PL/SQLRAWよりもはるかに簡単に操作できるバイナリ データ) です。BLOB

名前が示すように、RAWデータ型は生のバイナリ形式であり、そのまま格納されます (最初のブロックの長さバイトを除く)。したがって、この行に最適な格納スペースです。データ型は、パッケージRAWを使用して操作できます。SYS.UTL_RAWほとんどすべてのデータ型にキャストできます (ストレージ スキームが一致する場合)。たとえば、 は13でb1101はありませんが、NUMBER13 であり.PL_INTEGERVARCHAR2CHR(13)

UTL_RAWまた、 を使用してキャストするよりも簡単に行うことができます。HEXTORAWおよび関数は、 のデータの 16 進表現から にデータRAWTOHEXを前後にキャストします。たとえば、または両方の結果は;の値になります。ご覧のとおり、a の基本ブロックはバイトであるため、左側に余分なゼロが埋め込まれてバイトが形成されます。データ自体は、および他のストリームへの変換中にリトルエンディアン (最下位バイトがデータの右端のバイトに存在することを意味する) として機能しますが、そのような複雑なデータ型へのキャストでは、メモリをコピーするだけで、ゼロをパディングして必要な場合は左。RAWVARCHAR2HEXTORAW('d')HEXTORAW('D')RAWb00001101RAWVARCHAR2NUMBER

于 2015-04-20T17:39:13.503 に答える
-1

これが役立つかどうかはわかりませんが、NUMBER データ型とbin_to_num関数 を使用できます。

create table test_bin(num_val number, var_val varchar2(1000));

insert into test_bin values(bin_to_num(1,0,1,0,1,0,1,0), '10101010');

select dump(num_val, 17) n, dump(var_val, 17) v from test_bin;

n                     |   v
---------------------------------------------------
Typ=2 Len=3 c2,^B,G   |   Typ=1 Len=8 1,0,1,0,1,0,1,0

ご覧のとおり、ソーターです。8 バイトではなく 3 バイトしかありませんが、それでも 1 バイトではありません。

UPDATE それを1バイトにする方法が見つかりました:chr関数を使用できます

select dump(chr(bin_to_num(1,0,1,0,1,0,1,0))) c from dual;

n                   
--------------------
Typ=1 Len=1 170

したがって、varchar2 を使用し続けることができますが、8 ビットごとに char に変換するだけです。

于 2012-06-25T13:59:28.863 に答える