Byte PostgreSQL vs smallint []

9

Saya mencari untuk mengimpor data time-series multi-channel besar (100Mb - 1 GB) ke dalam database PostgreSQL. Data berasal dari file format EDF yang memecah data menjadi "catatan" atau "zaman" masing-masing beberapa detik. Setiap catatan zaman memegang sinyal untuk setiap saluran data sebagai array berurutan dari bilangan bulat pendek.

Saya diberi mandat untuk menyimpan file dalam database, dalam kasus terburuk sebagai BLOB. Karena itu, saya ingin menyelidiki opsi yang memungkinkan saya untuk melakukan sesuatu yang lebih dengan data dalam database, seperti memfasilitasi permintaan berdasarkan data sinyal.

Rencana awal saya adalah menyimpan data sebagai satu baris per catatan zaman. Yang ingin saya pertimbangkan adalah apakah menyimpan data sinyal aktual sebagai tipe bytea atau smallint [] (atau bahkan smallint [] []). Adakah yang bisa merekomendasikan satu di atas yang lain? Saya tertarik dengan biaya penyimpanan dan akses. Penggunaan cenderung disisipkan sekali, baca sesekali, perbarui tidak pernah. Jika seseorang lebih mudah dibungkus sebagai tipe kustom sehingga saya bisa menambahkan fungsi untuk menganalisis membandingkan catatan maka jauh lebih baik.

Tidak diragukan lagi saya kekurangan detail, jadi jangan ragu untuk menambahkan komentar tentang apa yang ingin Anda klarifikasi.

beldaz
sumber
2
Ini mungkin salah satu dari sedikit penggunaan yang masuk akal untuk penggunaan array dalam model data otoritatif, karena Anda menghemat banyak ruang disk dengan menghindari overhead baris 24 hingga 28-byte. Array juga dikompresi dan disimpan out of line jika cukup lama.
Craig Ringer
beldaz, cara Anda menyimpan data banyak terkait dengan bagaimana Anda berencana mengaksesnya, dan seberapa sering. Jika data jarang ditanyakan, dan Anda selalu ingin hanya menarik data berdasarkan per-catatan, maka saya pikir satu baris per rekaman dalam array masuk akal. Namun, jika Anda ingin melakukan kueri apa pun yang sedikit lebih mendalam, seperti menarik semua catatan untuk patient_id tertentu, misalnya, maka mungkin kami dapat menyarankan sedikit perbaikan pada struktur penyimpanan. Ada ide tentang pola kueri Anda?
Chris
@ Chris, terima kasih. Saya telah meninggalkan komponen metadata karena itu sangat kecil dan dapat berada dalam relasi yang terpisah. Pola kueri TBD, tetapi saya mungkin ingin membandingkan dua file berbeda yang direkam pada waktu yang sama, dan menarik sinyal dari zaman simultan.
beldaz
@CraigRinger Saya tidak melihat banyak bukti kompresi array. Apakah ini perlu diaktifkan dengan cara tertentu?
beldaz

Jawaban:

11

Dengan tidak adanya jawaban, saya sendiri sudah mengeksplorasi masalah ini.

Sepertinya fungsi yang ditentukan pengguna dapat menangani semua jenis basis, termasuk bytea dan smallint[], jadi ini tidak banyak mempengaruhi pilihan representasi.

Saya mencoba beberapa representasi berbeda pada server PostgreSQL 9.4 yang berjalan secara lokal pada laptop Windows 7 dengan konfigurasi vanilla. Relasi untuk menyimpan data sinyal aktual adalah sebagai berikut.

Objek Besar untuk seluruh file

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

Array KECIL per saluran

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 per saluran di setiap zaman

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

Susunan 2D KECIL per zaman

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

Array BYTEA per zaman

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

Saya kemudian mengimpor pilihan file EDF ke masing-masing hubungan ini melalui Java JDBC dan membandingkan pertumbuhan dalam ukuran database setelah setiap unggahan.

File-file itu adalah:

  • File A: 2706 zaman dari 16 saluran, masing-masing saluran 1024 sampel (16385 sampel per zaman), 85 MB
  • File B: 11897 zaman dari 18 saluran, masing-masing saluran 1024 sampel (18432 sampel per zaman), 418 MB
  • File C: 11746 zaman dari 20 saluran, masing-masing saluran 64 hingga 1024 sampel (17088 sampel per zaman), 382 MB

Dalam hal biaya penyimpanan, inilah ukuran yang digunakan dalam MB untuk setiap kasus: Biaya penyimpanan dalam MB

Relatif dengan ukuran file asli, Objek Besar sekitar 30-35% lebih besar. Sebaliknya, menyimpan setiap zaman sebagai BYTEA atau SMALLINT [] [] kurang dari 10% lebih besar. Menyimpan setiap saluran sebagai tuple terpisah memberikan peningkatan 40%, baik sebagai BYTEA atau SMALLINT [], jadi tidak jauh lebih buruk daripada menyimpan sebagai objek besar.

Satu hal yang saya awalnya tidak menghargai adalah bahwa "array Multidimensi harus memiliki luasan yang cocok untuk setiap dimensi" di PostgreSQL . Ini berarti bahwa SMALLINT[][]representasi hanya berfungsi ketika semua saluran dalam zaman memiliki jumlah sampel yang sama. Karenanya File C gagal bekerja dengan EpochArrayrelasi.

Dalam hal biaya akses, saya belum bermain-main dengan ini, tetapi setidaknya dalam hal memasukkan data pada awalnya representasi tercepat adalah EpochByteadan BlobFile, dengan EpochChannelArrayyang paling lambat, memakan waktu sekitar 3 kali lebih lama dari dua yang pertama.

beldaz
sumber
Dari perspektif akademis, saya menemukan hasil Anda sangat menarik, tetapi dari sudut pandang praktis, apakah ukuran penyimpanan menjadi perhatian besar? Mungkin dalam kasus penggunaan Anda, Anda memiliki sangat banyak catatan, dan penyimpanan adalah masalah yang Anda hadapi? Namun, dalam format penyimpanan ini, pencarian apa pun selain oleh zaman (atau saluran, ketika dalam skema yang sesuai) akan membutuhkan membaca sebagian dari setiap catatan. Apakah ini OK untuk aplikasi Anda?
Chris
Secara praktis ya, itu tentu penting bagi saya, karena saya berharap untuk berurusan dengan beberapa TB file mentah. Ternyata saat ini di overhead lebih rendah dari yang saya harapkan, tetapi jika sudah 300% untuk representasi tertentu saya pasti akan menghindarinya. Adapun permintaan, saya tidak akan mengharapkan untuk mengakses oleh apa pun selain zaman dan saluran.
beldaz