ブロブのバイトサイズを取得したいのですが。
Postgresqlを使用していますが、SQLクエリを使用してサイズを取得したいと思います。このようなもの:
SELECT sizeof(field) FROM table;
これはPostgresqlで可能ですか?
更新:postgresqlのマニュアルを読みましたが、ファイルサイズを計算するための適切な関数が見つかりませんでした。また、blobは大きなオブジェクトとして保存されます。
大きなオブジェクトを使用したわけではありませんが、ドキュメントを見てください: http://www.postgresql.org/docs/current/interactive/lo-interfaces.html#LO-TELL
一部のファイルシステムAPIが必要とするのと同じ手法を使用する必要があると思います。最後までシークしてから、位置を指定します。 PostgreSQLには、内部C関数をラップしているように見えるSQL関数があります。私は多くのドキュメントを見つけることができませんでしたが、これはうまくいきました:
CREATE OR REPLACE FUNCTION get_lo_size(oid) RETURNS bigint
VOLATILE STRICT
LANGUAGE 'plpgsql'
AS $$
DECLARE
fd integer;
sz bigint;
BEGIN
-- Open the LO; N.B. it needs to be in a transaction otherwise it will close immediately.
-- Luckily a function invocation makes its own transaction if necessary.
-- The mode x'40000'::int corresponds to the PostgreSQL LO mode INV_READ = 0x40000.
fd := lo_open($1, x'40000'::int);
-- Seek to the end. 2 = SEEK_END.
PERFORM lo_lseek(fd, 0, 2);
-- Fetch the current file position; since we're at the end, this is the size.
sz := lo_tell(fd);
-- Remember to close it, since the function may be called as part of a larger transaction.
PERFORM lo_close(fd);
-- Return the size.
RETURN sz;
END;
$$;
それをテストする:
-- Make a new LO, returns an OID e.g. 1234567
SELECT lo_create(0);
-- Populate it with data somehow
...
-- Get the length.
SELECT get_lo_size(1234567);
LO機能は、主にクライアントまたは低レベルのサーバープログラミングを通じて使用されるように設計されているようですが、少なくとも、SQLで表示される関数がいくつか提供されているため、上記が可能になります。開始するためにSELECT relname FROM pg_proc where relname LIKE 'lo%'
のクエリを実行しました。 Cプログラミングの漠然とした記憶と、モードx'40000'::int
およびSEEK_END = 2
値の少しの調査が残りに必要でした!
大きなオブジェクトを作成するときに、サイズを格納するようにアプリケーションを変更できます。それ以外の場合は、次のようなクエリを使用できます。
select sum(length(lo.data)) from pg_largeobject lo
where lo.loid=XXXXXX
以前の投稿で提案されているように、ラージオブジェクトAPI関数を使用することもできます。これらは正常に機能しますが、上記で提案されたselectメソッドよりも桁違いに遅くなります。
select pg_column_size(lo_get(lo_oid)) from table;
サイズをバイト単位で示します。
きれいな印刷が必要な場合:
select pg_size_pretty(pg_column_size(lo_get(lo_oid))::numeric) from table;
length()
またはoctet_length()
を試してください
これが私の解決策です:
select
lo.loid,
pg_size_pretty(sum(octet_length(lo.data)))
from pg_largeobject lo
where lo.loid in (select pg_largeobject.loid from pg_largeobject)
group by lo.loid;