Misalkan saya sedang membangun blog yang ingin saya posting dan komentar. Jadi saya membuat dua tabel, tabel 'posting' dengan kolom 'id' integer autoincrementing, dan tabel 'komentar' yang memiliki kunci asing 'post_id'.
Lalu saya ingin menjalankan apa yang mungkin akan menjadi permintaan paling umum saya, yaitu untuk mengambil posting dan semua komentarnya. Menjadi agak baru untuk database relasional, pendekatan yang tampak paling jelas bagi saya adalah menulis kueri yang akan terlihat seperti:
SELECT id, content, (SELECT * FROM comments WHERE post_id = 7) AS comments
FROM posts
WHERE id = 7
Yang akan memberi saya id dan konten posting yang saya inginkan, bersama dengan semua baris komentar yang relevan yang dikemas dengan rapi dalam array (representasi bersarang seperti yang akan Anda gunakan di JSON). Tentu saja, SQL dan basis data relasional tidak berfungsi seperti ini, dan yang paling dekat yang bisa mereka dapatkan adalah melakukan penggabungan antara 'posting' dan 'komentar' yang akan mengembalikan banyak duplikasi data yang tidak perlu (dengan informasi posting yang sama diulang di setiap baris), yang berarti waktu pemrosesan dihabiskan baik pada basis data untuk menggabungkan semuanya dan pada ORM saya untuk menguraikan dan membatalkan semuanya.
Bahkan jika saya menginstruksikan ORM saya untuk dengan bersemangat memuat komentar posting, yang terbaik akan lakukan adalah mengirimkan satu permintaan untuk posting, dan kemudian permintaan kedua untuk mengambil semua komentar, dan kemudian menyatukannya di sisi klien, yang juga tidak efisien.
Saya mengerti bahwa basis data relasional adalah teknologi yang telah terbukti (ya, mereka lebih tua dari saya), dan ada banyak penelitian yang dilakukan selama beberapa dekade, dan saya yakin ada alasan yang sangat bagus mengapa mereka (dan SQL standar) dirancang untuk berfungsi seperti yang mereka lakukan, tapi saya tidak yakin mengapa pendekatan yang saya sebutkan di atas tidak mungkin. Tampaknya bagi saya menjadi cara yang paling sederhana dan jelas untuk menerapkan salah satu hubungan paling mendasar antara catatan. Mengapa basis data relasional tidak menawarkan sesuatu seperti ini?
(Penafian: Saya kebanyakan menulis webapp menggunakan Rails dan NoSQL datastores, tetapi baru-baru ini saya sudah mencoba Postgres, dan saya sangat menyukainya. Saya tidak bermaksud menyerang basis data relasional, saya hanya bingung.)
Saya tidak bertanya bagaimana mengoptimalkan aplikasi Rails, atau cara meretas masalah ini di basis data tertentu. Saya bertanya mengapa standar SQL bekerja seperti ini ketika tampaknya berlawanan dengan intuisi dan boros bagi saya. Pasti ada beberapa alasan historis mengapa perancang SQL asli ingin hasil mereka terlihat seperti ini.
Jawaban:
Tanggal CJ menjelaskan lebih detail tentang ini di Bab 7 dan Lampiran B dari SQL dan Teori Relasional . Anda benar, tidak ada dalam teori relasional yang melarang tipe data atribut menjadi relasi itu sendiri, asalkan itu tipe relasi yang sama di setiap baris. Teladan Anda akan memenuhi syarat.
Tetapi Date mengatakan struktur seperti ini "biasanya - tetapi tidak selalu - dikontraindikasikan" (yaitu Ide Buruk) karena hierarki hubungan asimetris . Misalnya, transformasi dari struktur bersarang ke struktur "flat" yang sudah dikenal tidak selalu dapat dibalik untuk menciptakan kembali sarang.
Pertanyaan, kendala, dan pembaruan lebih kompleks, lebih sulit untuk ditulis, dan lebih sulit untuk didukung oleh RDBMS jika Anda mengizinkan atribut bernilai relasi (RVA).
Hal ini juga muddies basis data prinsip-prinsip desain, karena terbaik hirarki hubungan tidak begitu jelas. Haruskah kita merancang hubungan Pemasok dengan RVA bersarang untuk suku cadang yang dipasok oleh Pemasok tertentu? Atau hubungan Bagian dengan RVA bersarang untuk pemasok yang memasok Bagian tertentu? Atau simpan keduanya, untuk memudahkan menjalankan berbagai jenis kueri?
Ini adalah dilema yang sama yang dihasilkan dari basis data hierarkis dan model basis data berorientasi dokumen . Akhirnya, kompleksitas dan biaya mengakses struktur data bersarang mendorong perancang untuk menyimpan data secara berlebihan untuk pencarian yang lebih mudah dengan berbagai pertanyaan. Model relasional mencegah redundansi, sehingga RVA dapat bekerja melawan tujuan pemodelan relasional.
Dari apa yang saya pahami (saya belum menggunakannya), Rel dan Dataphor adalah proyek RDBMS yang mendukung atribut yang bernilai relasi.
Komentar ulang dari @dportas:
Tipe terstruktur adalah bagian dari SQL-99, dan Oracle mendukung ini. Tetapi mereka tidak menyimpan beberapa tupel di tabel bersarang per baris tabel dasar. Contoh umum adalah atribut "alamat" yang tampaknya merupakan satu kolom dari tabel dasar, tetapi memiliki sub-kolom lebih lanjut untuk jalan, kota, kode pos, dll.
Tabel bersarang juga didukung oleh Oracle, dan ini memungkinkan beberapa tupel per baris tabel dasar. Tetapi saya tidak sadar bahwa ini adalah bagian dari SQL standar. Dan ingatlah kesimpulan dari satu blog: "Saya tidak akan pernah menggunakan tabel bersarang dalam pernyataan CREATE TABLE. Anda menghabiskan seluruh waktu Anda MENG-NESTING mereka untuk menjadikannya berguna lagi!"
sumber
x
dapat memiliki nilai bilangan bulat 42). Operasi yang sama berlaku untuk relasi dan relade, sehingga strukturnya harus kompatibel.Beberapa sistem basis data paling awal didasarkan pada model Hierarchical Database . Ini mewakili data dalam struktur seperti pohon dengan orang tua dan anak-anak, seperti yang Anda sarankan di sini. HDMS sebagian besar digantikan oleh database yang dibangun di atas model relasional. Alasan utama untuk ini adalah bahwa RDBMS dapat memodelkan hubungan "banyak ke banyak" yang sulit untuk database hierarkis dan bahwa RDBMS dapat dengan mudah melakukan kueri yang bukan bagian dari desain asli sedangkan HDBMS membatasi Anda untuk melakukan kueri melalui jalur yang ditentukan pada waktu desain.
Masih ada beberapa contoh sistem basis data hierarkis di alam liar, khususnya jendela registri dan LDAP.
Cakupan luas dari subjek ini tersedia di artikel berikut
sumber
Saya kira pertanyaan Anda benar-benar terpusat pada fakta bahwa sementara basis data didasarkan pada logika yang kuat dan menetapkan dasar teroretik dan mereka melakukan pekerjaan yang sangat baik menyimpan, memanipulasi dan mengambil data dalam set (2 dimensi) sambil memastikan integritas referensial, konkurensi dan banyak hal lainnya, mereka tidak menyediakan fitur (tambahan) untuk mengirim (dan menerima) data dalam apa yang bisa disebut format berorientasi objek atau format hierarkis.
Lalu Anda mengklaim bahwa "bahkan jika saya memerintahkan ORM saya untuk dengan bersemangat memuat komentar posting, yang terbaik adalah mengirimkan satu permintaan untuk posting, dan kemudian permintaan kedua untuk mengambil semua komentar, dan kemudian menyatukannya sisi klien, yang juga tidak efisien " .
Saya tidak melihat sesuatu yang tidak efisien dalam mengirim 2 kueri dan menerima 2 kumpulan hasil dengan:
Saya berpendapat bahwa (hampir) cara yang paling efisien (hampir, karena Anda tidak benar-benar membutuhkan
posts.id
dan tidak semua kolom daricomments.*
)Seperti yang ditunjukkan Todd dalam komentarnya, Anda seharusnya tidak meminta database untuk mengembalikan data yang siap ditampilkan. Tugas aplikasi untuk melakukan itu. Anda dapat menulis (satu atau beberapa) pertanyaan untuk mendapatkan hasil yang Anda butuhkan untuk setiap operasi tampilan sehingga tidak ada duplikasi yang tidak perlu dalam data yang dikirim melalui kabel (atau bus memori) dari db ke aplikasi.
Saya benar-benar tidak dapat berbicara tentang ORM tetapi mungkin beberapa dari mereka dapat melakukan bagian dari pekerjaan ini untuk kami.
Teknik serupa dapat digunakan dalam pengiriman data antara server web dan klien. Teknik lain (seperti caching) digunakan sehingga basis data (atau web atau server lain) tidak kelebihan dengan permintaan duplikat.
Dugaan saya adalah bahwa standar, seperti SQL, adalah yang terbaik jika mereka tetap berspesialisasi dalam satu bidang dan tidak mencoba untuk mencakup semua bidang bidang.
Di sisi lain, komite yang menetapkan standar SQL mungkin berpikir sebaliknya di masa depan dan memberikan standarisasi untuk fitur tambahan tersebut. Tapi itu bukan sesuatu yang bisa dirancang dalam satu malam.
sumber
Saya tidak dapat menjawab dengan jawaban yang tepat dan diperdebatkan, jadi jangan ragu untuk mengabaikan saya jika saya salah (tapi tolong perbaiki saya agar kami dapat mempelajari sesuatu yang baru). Saya pikir alasannya adalah bahwa basis data relasional berpusat pada model relasional, yang pada gilirannya didasarkan pada sesuatu yang saya tidak tahu apa-apa tentang yang disebut "logika urutan pertama". Apa yang mungkin Anda tanyakan mungkin tidak sesuai secara konseptual dalam kerangka kerja matematika / logis yang dibangun di atas basis data. Selain itu, apa yang Anda tanyakan biasanya diselesaikan dengan mudah dengan basis data grafik, memberikan lebih banyak petunjuk bahwa itu adalah konsep dasar dari database yang bertentangan dengan apa yang ingin Anda capai.
sumber
Saya tahu setidaknya SQLServer mendukung kueri bersarang saat Anda menggunakan UNTUK XML.
Masalahnya di sini bukanlah kurangnya dukungan dari RDBMS, tetapi kurangnya dukungan tabel bersarang dalam tabel.
Selain itu, apa yang menghentikan Anda dari menggunakan gabungan dalam?
Anda dapat benar-benar melihat bagian dalam bergabung sebagai tabel bersarang, hanya konten dari 2 bidang pertama yang diulang suatu waktu. Saya tidak akan terlalu khawatir tentang kinerja dari join, satu-satunya bagian lambat dalam query seperti ini adalah io dari database ke klien. Ini hanya akan menjadi masalah ketika konten berisi sejumlah besar data. Dalam hal ini saya akan menyarankan dua pertanyaan, satu dengan
select id, content
dan satu dengan gabungan dalam danselect posts.id, comments.*
. Ini berskala bahkan dengan beberapa pos, karena Anda hanya akan menggunakan 2 kueri.sumber
for xml
.Sebenarnya Oracle mendukung apa yang Anda inginkan tetapi Anda harus membungkus sub-kueri dengan kata kunci "cursor". Hasil diambil melalui kursor terbuka. Di Jawa, misalnya komentar akan muncul sebagai set hasil. Lebih lanjut tentang ini, lihat dokumentasi Oracle pada "Ekspresi CURSOR"
sumber
Beberapa mendukung sarang (hierarkis).
Jika Anda menginginkan satu permintaan, Anda bisa memiliki satu tabel yang mereferensikan dirinya sendiri. Beberapa RDMS mendukung konsep ini. Misalnya, dengan SQL Server seseorang dapat menggunakan Common Table Expressions (CTEs) untuk kueri hierarki.
Dalam kasus Anda Postingan akan berada di Level 0 dan kemudian semua komentar akan berada di Level 1.
Opsi lainnya adalah 2 kueri atau Gabung dengan beberapa informasi tambahan untuk setiap catatan yang dikembalikan (yang orang lain telah sebutkan).
Contoh Hierarkis:
https://stackoverflow.com/questions/14274942/sql-server-cte-and-recursion-example
Di tautan di atas, EmpLevel menunjukkan level dari sarang (atau hierarki).
sumber
Maaf, saya tidak yakin saya benar-benar memahami masalah Anda.
Di MSSQL Anda bisa menjalankan 2 Pernyataan SQL.
Dan itu akan mengembalikan 2 set hasil Anda secara bersamaan.
sumber
RDBM didasarkan pada teori dan mereka berpegang pada teori. Ini memungkinkan konsistensi yang bagus, dan keandalan yang terbukti secara matematis.
Karena modelnya sederhana dan didasarkan pada teori, membuatnya mudah bagi orang untuk melakukan optimasi dan banyak implementasi. Ini tidak seperti NoSQL di mana setiap orang melakukannya sedikit berbeda.
Ada upaya di masa lalu untuk membuat database hierarkis tetapi IIRC (sepertinya tidak melihatnya) ada masalah (siklus dan kesetaraan muncul dalam pikiran).
sumber
Anda memiliki kebutuhan spesifik. Akan lebih baik untuk mengekstrak data dari database dalam format yang Anda inginkan, sehingga Anda dapat melakukannya dengan apa yang Anda inginkan.
Beberapa hal yang tidak dilakukan dengan baik oleh basis data, tetapi bagaimanapun juga bukan tidak mungkin untuk membangunnya. Meninggalkan pemformatan ke aplikasi lain adalah rekomendasi saat ini, tetapi tidak membenarkan mengapa itu tidak dapat dilakukan.
Satu-satunya argumen yang saya miliki terhadap saran Anda adalah dapat menangani hasil ini dengan cara "sql". Ini akan menjadi ide yang buruk untuk membuat hasil dalam database dan tidak dapat bekerja dengannya atau memanipulasinya sampai batas tertentu. Katakanlah saya membuat tampilan yang dibangun seperti yang Anda sarankan, bagaimana cara saya memasukkannya dalam pernyataan pilih lain? Database suka mengambil hasil dan melakukan sesuatu dengannya. Bagaimana saya akan bergabung ke meja lain? Bagaimana saya membandingkan hasil yang Anda set dengan yang lain?
Maka manfaat dari RDMS adalah fleksibilitas sql. Sintaks untuk memilih data dari tabel cukup dekat dengan daftar pengguna atau objek lain dalam sistem (Setidaknya itulah tujuannya.). Tidak yakin ada gunanya melakukan sesuatu yang sama sekali berbeda. Mereka bahkan tidak sampai pada titik penanganan kode prosedural / kursor atau BLOBS data dengan sangat efisien.
sumber
Menurut pendapat saya itu sebagian besar karena SQL dan cara permintaan agregat dilakukan - fungsi agregat dan pengelompokan dieksekusi pada rowset 2-dimensi besar untuk mengembalikan hasil. Begitulah cara itu sejak awal dan sangat cepat (sebagian besar solusi NoSQL cukup lambat dengan agregasi dan mengandalkan skema denormalized alih-alih kueri kompleks)
Tentu saja PostgreSQL memiliki beberapa fitur dari database berorientasi objek. Menurut email ini ( pesan ) Anda dapat mencapai apa yang Anda butuhkan dengan membuat agregat khusus.
Secara pribadi saya menggunakan kerangka kerja seperti Doctrine ORM (PHP) yang melakukan sisi aplikasi agregasi dan fitur pendukung seperti lazy-loading untuk meningkatkan kinerja.
sumber
PostgreSQL mendukung berbagai tipe data terstruktur, termasuk Array dan JSON . Menggunakan SQL atau salah satu bahasa prosedural tertanam, Anda dapat membangun nilai-nilai dengan struktur rumit yang sewenang-wenang dan mengembalikannya ke aplikasi Anda. Anda juga dapat membuat tabel dengan kolom dari salah satu tipe terstruktur, meskipun Anda harus hati-hati mempertimbangkan apakah Anda mendenormalisasi desain Anda.
sumber