2012-04-16 27 views
9

Tôi muốn lấy kích thước byte của một đốm màu.Nhận kích thước của đối tượng lớn trong truy vấn PostgreSQL?

Tôi đang sử dụng Postgresql và muốn lấy kích thước bằng truy vấn SQL. Một cái gì đó như thế này:

SELECT sizeof(field) FROM table; 

Điều này có thể thực hiện được trong Postgresql không?

Cập nhật: Tôi đã đọc hướng dẫn sử dụng postgresql và không thể tìm thấy hàm thích hợp để tính kích thước tệp. Ngoài ra, blob được lưu trữ như một đối tượng lớn.

+0

Vui lòng đọc hướng dẫn trước khi gửi bài như vậy một câu hỏi: http://www.postgresql.org/docs/current/static/functions.html –

+2

Xác định "dữ liệu blob ". Một cột bytea'? Hoặc một đối tượng lớn được lưu trữ trong 'pg_largeobject'? Hiển thị định nghĩa bảng của bạn. –

+0

Bản sao của [Lấy kích thước của lobject trong PostgresSQL] (http://stackoverflow.com/questions/9248738/obtaining-the-size-of-lobject-in-postgressql)? –

Trả lời

12

Không phải là tôi đã sử dụng các đối tượng lớn, nhưng nhìn vào tài liệu: http://www.postgresql.org/docs/current/interactive/lo-interfaces.html#LO-TELL

Tôi nghĩ rằng bạn phải sử dụng kỹ thuật tương tự như một số API hệ thống tập tin yêu cầu: tìm cách cuối cùng, sau đó nói với vị trí. PostgreSQL có các hàm SQL xuất hiện để bọc các hàm C bên trong. Tôi không thể tìm thấy nhiều tài liệu, nhưng điều này đã làm việc:

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; 
$$; 

kiểm tra nó:

-- 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); 

Có vẻ như các chức năng LO được thiết kế để được sử dụng chủ yếu là thông qua các khách hàng hoặc thông qua lập trình máy chủ cấp thấp , nhưng ít nhất họ đã cung cấp một số hàm có thể nhìn thấy SQL cho nó, điều này làm cho điều trên có thể xảy ra. Tôi đã truy vấn SELECT relname FROM pg_proc where relname LIKE 'lo%' để bắt đầu. Những ký ức mơ hồ về lập trình C và một chút nghiên cứu cho chế độ x'40000'::int và giá trị SEEK_END = 2 là cần thiết cho phần còn lại!

3

Hãy thử length() hoặc octet_length()

10

Bạn có thể thay đổi ứng dụng của mình để lưu trữ kích thước khi bạn tạo đối tượng lớn. Nếu không, bạn có thể sử dụng một truy vấn như:

select sum(length(lo.data)) from pg_largeobject lo 
where lo.loid=XXXXXX 

Bạn có thể sử dụng cũng là chức năng đối tượng API lớn, như đề xuất trong một bài trước, họ làm việc ok, nhưng là một thứ tự cường độ chậm hơn so với các lựa chọn phương pháp gợi ý ở trên .

+0

Đây là giải pháp sạch nhất. Cảm ơn – MarekM

+1

Thật không may, danh mục 'pg_largeobject' không còn có thể truy cập công khai nữa kể từ PostgreSQL 9.0: https://www.postgresql.org/docs/current/static/catalog-pg-largeobject.html. – ochedru

4
select pg_column_size(lo_get(lo_oid)) from table; 

Cung cấp cho bạn kích thước tính theo byte.

Nếu bạn muốn in ấn khá:

select pg_size_pretty(pg_column_size(lo_get(lo_oid))::numeric) from table; 
Các vấn đề liên quan