PostgreSQL bytea vs smallint []


9

Tôi đang tìm cách nhập dữ liệu chuỗi thời gian đa kênh lớn (100Mb - 1 GB) vào cơ sở dữ liệu PostgreQuery. Dữ liệu đến từ các tệp định dạng EDF chia dữ liệu thành "bản ghi" hoặc "kỷ nguyên" thường là vài giây mỗi lần. Mỗi bản ghi của epoch giữ các tín hiệu cho từng kênh dữ liệu dưới dạng các dãy liên tiếp của các số nguyên ngắn.

Tôi bắt buộc phải lưu trữ các tệp trong cơ sở dữ liệu, trong trường hợp xấu nhất là BLOB. Do đó, tôi muốn điều tra các tùy chọn cho phép tôi làm gì đó nhiều hơn với dữ liệu trong cơ sở dữ liệu, chẳng hạn như tạo điều kiện truy vấn dựa trên dữ liệu tín hiệu.

Kế hoạch ban đầu của tôi là lưu trữ dữ liệu dưới dạng một hàng trên mỗi bản ghi kỷ nguyên. Điều tôi đang cố gắng cân nhắc là lưu trữ dữ liệu tín hiệu thực tế dưới dạng các loại bytea hay smallint [] (hoặc thậm chí smallint [] []). Bất cứ ai có thể đề nghị cái này hơn cái kia? Tôi quan tâm đến chi phí lưu trữ và truy cập. Cách sử dụng có khả năng được chèn một lần, thỉnh thoảng đọc, cập nhật không bao giờ. Nếu một loại được gói dễ dàng hơn như một loại tùy chỉnh để tôi có thể thêm các chức năng để phân tích so sánh các bản ghi thì càng nhiều càng tốt.

Không còn nghi ngờ gì nữa, tôi rất ít chi tiết, vì vậy hãy thoải mái thêm ý kiến ​​về những gì bạn muốn tôi làm rõ.


2
Đây có thể là một trong số ít những cách sử dụng hợp lý cho việc sử dụng mảng trong mô hình dữ liệu có thẩm quyền, vì bạn tiết kiệm được nhiều không gian đĩa bằng cách tránh chi phí hàng 24 đến 28 byte. Mảng cũng được nén và lưu trữ ngoài dòng nếu đủ lâu.
Craig Ringer

beldaz, cách bạn nên lưu trữ dữ liệu có liên quan nhiều đến cách bạn dự định truy cập dữ liệu đó và mức độ thường xuyên. Nếu dữ liệu hiếm khi được truy vấn và bạn luôn muốn chỉ kéo dữ liệu trên cơ sở mỗi bản ghi, thì tôi nghĩ rằng một hàng trên mỗi bản ghi trong một mảng có ý nghĩa tốt. Tuy nhiên, nếu bạn muốn thực hiện bất kỳ truy vấn nào sâu hơn một chút, chẳng hạn như kéo lên tất cả các bản ghi cho một bệnh nhân đã cho, chẳng hạn, thì có lẽ chúng tôi có thể đề xuất cải thiện một chút cho cấu trúc lưu trữ. Bất kỳ ý tưởng về các mẫu truy vấn của bạn?
Chris

@Chris Cảm ơn. Tôi đã bỏ qua thành phần siêu dữ liệu vì nó rất nhỏ và có thể nằm trong một mối quan hệ riêng. Các mẫu truy vấn là TBD, nhưng tôi có thể muốn so sánh hai tệp khác nhau được ghi cùng một lúc và rút ra các tín hiệu từ các kỷ nguyên đồng thời.
beldaz

@CraigRinger Tôi không thấy nhiều bằng chứng về nén mảng. Điều này cần phải được kích hoạt theo một cách nào đó?
beldaz

Câu trả lời:


11

Trong trường hợp không có bất kỳ câu trả lời nào, tôi đã tự mình khám phá vấn đề này.

Có vẻ như các hàm do người dùng xác định có thể xử lý tất cả các loại cơ sở, bao gồm byteasmallint[], do đó, điều này không ảnh hưởng nhiều đến sự lựa chọn đại diện.

Tôi đã thử một số cách trình bày khác nhau trên máy chủ PostgreQuery 9.4 chạy cục bộ trên máy tính xách tay Windows 7 có cấu hình vanilla. Các mối quan hệ để lưu trữ dữ liệu tín hiệu thực tế như sau.

Đối tượng lớn cho toàn bộ tệp

CREATE TABLE BlobFile (
    eeg_id INTEGER PRIMARY KEY,
    eeg_oid OID NOT NULL
);

Mảng SMALLINT trên mỗi kênh

CREATE TABLE EpochChannelArray (
    eeg_id INT NOT NULL,
    epoch INT NOT NULL,
    channel INT,
    signal SMALLINT[] NOT NULL,
    PRIMARY KEY (eeg_id, epoch, channel)
);

BYTEA mỗi kênh trong mỗi kỷ nguyên

CREATE TABLE EpochChannelBytea (
    eeg_id INT NOT NULL,
    epoch INT NOT NULL,
    channel INT,
    signal BYTEA NOT NULL,
    PRIMARY KEY (eeg_id, epoch, channel)
);

Mảng 2D SMALLINT mỗi epoch

CREATE TABLE EpochArray (
    eeg_id INT NOT NULL,
    epoch INT NOT NULL,
    signals SMALLINT[][] NOT NULL,
    PRIMARY KEY (eeg_id, epoch)
);

Mảng BYTEA mỗi epoch

CREATE TABLE EpochBytea (
    eeg_id INT NOT NULL,
    epoch INT NOT NULL,
    signals BYTEA NOT NULL,
    PRIMARY KEY (eeg_id, epoch)
);

Sau đó, tôi đã nhập một lựa chọn các tệp EDF vào từng quan hệ này thông qua Java JDBC và so sánh sự tăng trưởng về kích thước cơ sở dữ liệu sau mỗi lần tải lên.

Các tập tin là:

  • Tệp A: 2706 epoch của 16 kênh, mỗi kênh 1024 mẫu (16385 mẫu mỗi epoch), 85 MB
  • Tệp B: 11897 epoch của 18 kênh, mỗi kênh 1024 mẫu (18432 mẫu mỗi epoch), 418 MB
  • Tệp C: 11746 epoch của 20 kênh, mỗi kênh 64 đến 1024 mẫu (17088 mẫu mỗi epoch), 382 MB

Về chi phí lưu trữ, đây là kích thước chiếm MB trong mỗi trường hợp: Chi phí lưu trữ tính bằng MB

Liên quan đến kích thước tệp gốc, Đối tượng lớn lớn hơn khoảng 30 - 35%. Ngược lại, lưu trữ mỗi kỷ nguyên dưới dạng BYTEA hoặc SMALLINT [] [] lớn hơn 10%. Lưu trữ mỗi kênh dưới dạng một bộ riêng biệt giúp tăng 40%, vì BYTEA hoặc SMALLINT [], vì vậy không tệ hơn nhiều so với việc lưu trữ dưới dạng một đối tượng lớn.

Một điều tôi ban đầu không đánh giá cao là "Mảng nhiều chiều phải có phạm vi phù hợp cho từng chiều" trong PostgreQuery . Điều này có nghĩa là SMALLINT[][]đại diện chỉ hoạt động khi tất cả các kênh trong một kỷ nguyên có cùng số lượng mẫu. Do đó File C không hoạt động với EpochArraymối quan hệ.

Trong nhiệm kỳ làm chi phí truy cập, tôi đã không chơi xung quanh với điều này, nhưng ít nhất về cách chèn các dữ liệu ban đầu đại diện nhanh nhất là EpochByteaBlobFile, với EpochChannelArraysự chậm nhất, lấy khoảng 3 lần miễn là hai người đầu tiên.


Từ góc độ học thuật, tôi thấy kết quả của bạn rất thú vị, nhưng từ quan điểm thực tế, kích thước lưu trữ có phải là mối quan tâm lớn? Có lẽ trong trường hợp sử dụng của bạn, bạn có rất nhiều hồ sơ, và vì vậy lưu trữ là vấn đề bạn gặp phải? Tuy nhiên, trong định dạng lưu trữ này, bất kỳ tra cứu nào khác ngoài epoch (hoặc kênh, khi trong lược đồ thích hợp) sẽ yêu cầu đọc một phần của mỗi bản ghi. Điều này có ổn cho ứng dụng của bạn không?
Chris

Thực tế là có, nó chắc chắn rất quan trọng đối với tôi, vì tôi đang mong đợi xử lý một vài TB tệp thô. Vì hóa ra dòng điện trên không thấp hơn tôi mong đợi, nhưng nếu nó là 300% cho một đại diện cụ thể thì tôi chắc chắn sẽ tránh được. Đối với truy vấn, tôi sẽ không truy cập bằng bất cứ thứ gì ngoài epoch và kênh.
beldaz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.