Alternatif untuk EAV untuk bidang dinamis di gudang data skema bintang

13

Saya perlu mendukung bidang dan nilai dinamis di pusat data besar untuk menyimpan log permintaan API, kasus pengguna saya adalah bahwa saya perlu menyimpan semua string permintaan API dan dapat melakukan kueri terhadap mereka di masa mendatang (jadi bukan hanya penyimpanan, jadi saya tidak bisa menggunakan gumpalan untuk mereka)

misalnya http://example.com/?action=test&foo=abc&bar=def...

Saya perlu menyimpan semua field => valuepemetaan, yaitu (action => test), (foo => abc), (bar => def), dan karena bidangnya sangat dinamis, satu-satunya solusi yang saya temukan adalah menggunakan Entity-Attribute-Value, namun, orang-orang terus mengatakan itu adalah desain yang sangat buruk.

Jadi, pertimbangkan kasus penggunaan saya di atas, apa alternatif yang cocok untuk EAV?

Skema saya saat ini menggunakan KAV

  1. Tabel requests
    (id, timestamp, uri)
    misalnya(1, 149382220, '/')

  2. Tabel params
    (request_id, key, value)
    misalnya(1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')

Ada saran?

Pembaruan: Kami menjalankan gudang di AWS RedShift

Howard
sumber
2
Apa yang salah dengan mencoba apa yang Anda sarankan pada database dev? Juga, apakah Anda berbicara tentang SQL Server? The sql tag cukup luas.
Max Vernon
Diperbarui pertanyaan saya
Howard
1
DBMS mana yang Anda gunakan? Beberapa memiliki kemampuan pengindeksan teks yang cukup bagus, jadi saya tidak akan mengesampingkan penggunaan bidang "teks panjang" untuk menyimpan permintaan. Karena itu, saya tidak akan memiliki masalah menggunakan model yang Anda usulkan. Sementara EAV dalam arti yang ketat, itu hanya digunakan untuk tujuan yang sangat spesifik ini. Sekali lagi, setelah mengatakan itu, pertanyaan macam apa yang perlu Anda lakukan? Coba dan tulis pertanyaan ini terhadap model ini untuk melihat apakah itu cocok untuk Anda.
Colin 't Hart
1
RDBMS apa yang Anda gunakan? SQLtidak cukup spesifik. Anda telah diminta dua kali. Saya yang ketiga.
Erwin Brandstetter
2
Karena RedShift didasarkan pada PostgreSQL, saya akan mencoba menggunakan hstoreatau jsontipe data (atau jsonbjika / ketika mereka "upgrade" ke 9,4).
Colin 't Hart

Jawaban:

11

Saya dapat memikirkan tiga solusi - EAV, XML, dan Sparse Columns. Yang terakhir ini khusus untuk vendor dan mungkin tidak berguna bagi Anda.

Metode apa pun yang Anda pilih, Anda mungkin ingin mempertimbangkan untuk menyimpan data permintaan asli dalam format mentah, dalam tabel atau file datar. Ini akan membuatnya mudah untuk mencoba cara-cara baru menyimpan data, memungkinkan Anda untuk memuat ulang data jika Anda menemukan kesalahan dengan cara Anda mem-parsing permintaan Anda, dan menawarkan peluang untuk mem-parsing permintaan API menggunakan pemrosesan batch atau "data besar" alat jika Anda menemukan bahwa gudang data Anda tidak dapat menangani data secara efisien.

Pertimbangan EAV

EAV / KVS, seperti yang telah Anda jelaskan di atas, kemungkinan merupakan implementasi yang paling mudah.

Sayangnya itu juga akan menjadi sangat mahal - untuk mendapatkan segala jenis pertanyaan efisien pada kunci yang biasa digunakan, Anda perlu memiliki indeks pada kolom kunci, yang bisa menjadi sangat terfragmentasi. Permintaan kunci tertentu akan sangat mahal.

Anda mungkin dapat mengurangi biaya pengindeksan atau pemindaian indeks dengan mendukung toko EAV Anda dengan tampilan terwujud (banyak vendor mendukung ini) untuk menanyakan kunci atau nilai yang Anda pedulikan.

XML

Sebagian besar sistem basis data perusahaan menawarkan penanganan XML yang sangat matang, termasuk validasi, pengindeksan, dan kueri canggih.

Memuat permintaan API ke dalam database karena XML akan menyediakan satu tuple per permintaan, yang secara logis mungkin sedikit lebih cocok untuk Anda daripada memiliki jumlah baris yang tidak diketahui dalam tabel EAV.

Apakah ini efisien akan sangat tergantung pada vendor RDBMS Anda dan implementasi Anda.

Kelemahan terbesar adalah bahwa ini mungkin satu-satunya cara mengelola data yang lebih rumit daripada manipulasi string dari permintaan asli!

Kolom Jarang / tabel tradisional

Mungkin Anda bisa memuat data Anda ke dalam struktur tabel tradisional, dengan satu kolom per kunci.

Fitur SQL Server's Sparse Columns adalah alternatif yang bagus untuk toko EAV. Tabel dengan Kolom Jarang berperilaku sama seperti tabel normal, kecuali bahwa tabel tersebut dapat memiliki hingga 30.000 kolom, dan nilai NULL dalam kolom jarang tidak menggunakan ruang dalam tabel.

Menggabungkannya dengan Indeks yang Difilter (fitur spesifik SQL Server lain) dapat memberikan alternatif yang sangat efisien untuk toko EAV jika Anda sering meminta beberapa kolom dan / atau nilai tertentu.

Menggunakan tabel tradisional dengan vendor lain mungkin layak - IBM mendukung lebih dari 700 kolom per tabel dan Oracle sekitar 1000, dan fitur seperti kompresi atau perlakuan Oracle terhadap trailing nulls dapat berarti bahwa Anda dapat menyimpan data API Anda dengan cukup efisien.

Kelemahan yang jelas dari pendekatan ini adalah bahwa ketika Anda menambahkan kunci baru ke API Anda, Anda harus menyesuaikan skema Anda.

Nathan Jolly
sumber
2
Dalam PostgreSQL saya tidak akan merekomendasikan XML tetapi salah satu hstoreatau json. Dalam 9,4 mendatang jsonbakan menjadi rekomendasi saya.
Colin 't Hart
Saya sangat suka jawaban ini dengan pro kontra dan penjelasan masing-masing. Sangat informatif - Saya sangat menghargai info Jarang Kolom. Saya ingin contoh EAV menggunakan pendekatan kolom jarang.
StixO
9

EAV bukanlah desain yang buruk, karena itu, EAV hanyalah desain yang membutuhkan pemikiran yang matang dan dapat dipadukan dengan masalah kinerja seiring dengan meningkatnya jumlah data. Mungkin untuk sistem Anda, itu akan bekerja dengan baik.

Ketika saya mendesain sistem untuk menyimpan string kueri, saya tidak tahu sebelumnya bidang apa yang akan saya minati. Saya membuat tabel untuk menyimpan string kueri dalam format biner serial, dan membangun sistem yang memungkinkan saya untuk memecah kueri. merangkai bagian-bagian komponennya begitu saya tahu bagian yang saya minati. Dari sana saya membuat satu set tabel; masing-masing untuk set data yang biasanya terkandung dalam string kueri.

Misalnya, saya akhirnya memiliki tabel untuk data pengarah, satu untuk data permintaan target, dan satu untuk item terkait pengguna seperti permintaan pencarian yang mereka masukkan.

Saya menemukan kemampuan untuk menyimpan seluruh string kueri dalam satu tabel sebagai gumpalan, sambil memberikan kemampuan untuk memisahkan gumpalan itu di masa depan, memenuhi kebutuhan saya dengan sangat baik.

Max Vernon
sumber
1
Baik dalam pertanyaan dan jawaban istilah BLOByang digunakan yang berarti Binary Long OBject. Saya lebih suka menggunakan CLOB(Character Long OBject) atau sesuatu seperti textdi PostgreSQL, karena kita berbicara tentang karakter dan bukan data biner.
Colin 't Hart
2
Saya menggunakan bidang biner karena saya benar-benar membuat serial seluruh objek sesi dan menyimpan semuanya dalam database.
Max Vernon