1

私の場合:

多くの部分に分割されたバイナリデータがあります。FileParts、、fileIdおよびpartNoを含む特別なテーブルdata

すべてのパーツを別のテーブルにまとめる必要がありますMyFilesStorage

今、私は2つの実現から選択しています:

DO $CODE$
declare
  r record;
begin
  UPDATE public.MyFilesStorage SET mainFileData = E''::bytea WHERE id = 'e14a26c0-db4b-47e1-8b66-e091fb3ba199'::uuid;

  for r in ( select data 
             from public.FileParts 
             where fileId = '89cb8598-436b-49b3-bb1c-34534c6d068e'::uuid
             order by partNo ) loop
    UPDATE public.MyFilesStorage SET mainFileData = mainFileData || r.data WHERE id = 'e14a26c0-db4b-47e1-8b66-e091fb3ba199'::uuid;
  end loop;

end;
$CODE$

データを空に設定し、パーツを 1 つずつ読み取り、各パーツをメイン テーブルに追加します。

別のバリアント:

DO $CODE$
declare
  r record;
  p_result bytea;
begin
  p_result = E''::bytea;

  for r in ( select data 
             from public.FileParts 
             where fileId = '89cb8598-436b-49b3-bb1c-34534c6d068e'::uuid
             order by partNo ) loop
    p_result = p_result || r.data;
  end loop;

  UPDATE public.MyFilesStorage SET mainFileData = p_result WHERE id = 'e14a26c0-db4b-47e1-8b66-e091fb3ba199'::uuid;
end;
$CODE$

ここでは一時変数を使用します。2番目ははるかに高速ですが、どちらがより多くのメモリを必要とするかわかりませんか? 最初にすべてのファイルを RAM にロードするためにメモリが必要ですか? postgre はすべてのコンテンツをここに読み込みます: mainFileData = mainFileData || r.data?

両方のバリアントが非常に遅いため、これを行う別の方法があるのではないでしょうか? オラクルではDBMS_LOB.APPEND、この操作に使用します。

4

2 に答える 2

3

最初のバージョンは、PostgreSQLがストレージレベルでインプレース更新を行わないため遅くなり、UPDATEごとに行の新しいバージョンが作成されます。したがって、0Mbから100MBまで10Mbずつ増加する行の場合、実際にディスクに書き込まれるのは10x10Mbではなく、10Mb + 20Mb + 30Mb + ... + 90Mb + 100Mb= 550Mbです。一方、メモリ消費量は低く抑えられ、一度に10Mb以下がメモリに割り当てられます。

2番目のバージョンは書き込みが100Mbしかないため高速ですが、メモリに100Mbを割り当てる必要があります。

順序付けられたチャンクを持つテーブルの構造は、FileParts一般に大きなコンテンツの管理が簡単ですが、なぜそれをモノリシックな他の構造に変換するのが面倒なのですか?

于 2012-04-17T19:44:33.717 に答える
3

あなたのアプローチは正しいように見えます。ここで PostgreSQL のマニュアルを確認してください。

独自の集計を定義して、ジョブを実行することもできます。

CREATE AGGREGATE bytea_add(bytea)
(
    sfunc = byteacat,
    stype = bytea,
    initcond = E''
);

そして、次のような一般的な SQL を使用します。

UPDATE public.MyFIlesStorage SET mainFileData = (
    SELECT bytea_add(data) FROM public.FileParts
     WHERE fileId = '89cb8598-436b-49b3-bb1c-34534c6d068e'::uuid
     -- ORDER BY partNo -- ORDER BY partNo will not work
 )
 WHERE id = 'e14a26c0-db4b-47e1-8b66-e091fb3ba199'::uuid;

編集:

UPDATE public.MyFilesStorage mfs SET mainFileData = fp.all_data
  FROM (
    SELECT bytea_add(data) OVER (ORDER BY partNo) AS all_data,
           rank() OVER (ORDER BY partNo DeSC) AS pos
      FROM public.FileParts
     WHERE fileId = '89cb8598-436b-49b3-bb1c-34534c6d068e'::uuid
 ) AS fp
 WHERE fp.pos = 1
   AND mfs.id = 'e14a26c0-db4b-47e1-8b66-e091fb3ba199'::uuid;

内部 SQL の出力を個別に確認できます。

于 2012-04-17T16:09:13.600 に答える