MySQL: banyak tabel atau satu tabel dengan banyak kolom?

125

Jadi ini lebih merupakan pertanyaan desain.

Saya memiliki satu kunci utama (katakanlah ID pengguna), dan saya memiliki banyak informasi yang terkait dengan pengguna itu.

Haruskah saya memiliki beberapa tabel yang dipecah menjadi kategori sesuai dengan informasi, atau haruskah saya hanya memiliki satu tabel dengan banyak kolom?

Cara yang biasa saya lakukan adalah memiliki banyak tabel, jadi katakanlah, satu tabel untuk data penggunaan aplikasi, satu tabel untuk info profil, satu tabel untuk token back end, dll. Agar semuanya tetap teratur.

Baru-baru ini seseorang mengatakan kepada saya bahwa lebih baik tidak melakukannya seperti itu dan memiliki tabel dengan banyak kolom tidak masalah. Masalahnya, semua kolom itu memiliki kunci utama yang sama.

Saya cukup baru dalam desain database jadi pendekatan mana yang lebih baik dan apa pro dan kontra?

Apa cara konvensional melakukannya?

Xavier_Ex
sumber
Untuk kejelasan, perbaiki saya jika saya salah, tetapi menurut saya "beberapa tabel" dapat dipahami sebagai tabel tautan / asosiatif: en.wikipedia.org/wiki/Associative_entity
cellepo
1
Apakah database ini diperlukan untuk tujuan analitis atau untuk pemrosesan operasional / transaksional?
Alexander Radev

Jawaban:

112

Setiap informasi waktu adalah satu-ke-satu (setiap pengguna memiliki satu nama dan kata sandi), maka mungkin lebih baik untuk memiliki satu tabel, karena mengurangi jumlah gabungan yang perlu dilakukan database untuk mengambil hasil. Saya pikir beberapa database memiliki batasan pada jumlah kolom per tabel, tetapi saya tidak akan mengkhawatirkannya dalam kasus normal, dan Anda selalu dapat membaginya nanti jika perlu.

Jika datanya satu-ke-banyak (setiap pengguna memiliki ribuan baris info penggunaan), maka itu harus dipecah menjadi tabel terpisah untuk mengurangi data duplikat (data duplikat menghabiskan ruang penyimpanan, ruang cache, dan membuat database lebih sulit untuk dipelihara ).

Anda mungkin menemukan artikel Wikipedia tentang normalisasi database menarik, karena membahas alasannya secara mendalam:

Normalisasi database adalah proses pengorganisasian kolom dan tabel database relasional untuk meminimalkan redundansi dan ketergantungan. Normalisasi biasanya melibatkan pembagian tabel besar menjadi tabel yang lebih kecil (dan tidak terlalu berlebihan) dan menentukan hubungan di antara mereka. Tujuannya adalah untuk mengisolasi data sehingga penambahan, penghapusan, dan modifikasi bidang dapat dilakukan hanya dalam satu tabel dan kemudian disebarkan ke seluruh database melalui hubungan yang ditentukan.

Denormalisasi juga merupakan sesuatu yang harus diperhatikan, karena ada kasus di mana pengulangan data lebih baik (karena mengurangi jumlah pekerjaan yang perlu dilakukan database saat membaca data). Saya sangat menyarankan untuk membuat data Anda senormal mungkin untuk memulai, dan hanya melakukan denormalisasi jika Anda mengetahui masalah kinerja dalam kueri tertentu.

Brendan Long
sumber
Terima kasih atas jawaban Anda, jadi setelah membacanya saya pikir apa yang saya bicarakan adalah situasi informasi satu-ke-satu, ketika pengguna memiliki banyak kolom satu-ke-satu.
Xavier_Ex
@Xavier_Ex - Ya, jika hanya ada satu kolom per pengguna, maka hanya satu tabel pengguna yang besar akan lebih mudah untuk digunakan (dan jauh lebih mudah untuk mesin DB untuk mengoptimalkan).
Brendan Long
Posting yang Anda edit memberikan informasi yang lebih berguna! Saya memiliki kekhawatiran baru bahwa jika beberapa kolom akan sering diperbarui, haruskah saya meletakkannya di tabel terpisah? Misalnya tanggal lahir pengguna tidak akan pernah diperbarui, tetapi token ujung belakang mungkin tidak valid setelah jangka waktu tertentu dan akan memerlukan pembaruan yang sering. Apakah lebih baik jika saya memisahkan tabel dengan cara ini untuk meningkatkan kinerja? Sekarang saya akan membaca tentang wiki yang Anda sebutkan :)
Xavier_Ex
@Xavier_Ex - Saya tidak akan merekomendasikannya. Anda mendapatkan kinerja yang jauh lebih baik ketika Anda dapat mencari semua data yang Anda butuhkan dalam satu tabel (lihat artikel denormalisasi). Penggabungan itu mahal karena (1) mereka memerlukan pencarian data di banyak tempat, yang dapat melibatkan pencarian pada disk yang berputar, (2) umumnya membutuhkan banyak indeks dan semacam penggabungan, dan (3) mereka membuat perencanaan kueri lebih sulit, yang tidak hanya membutuhkan waktu, tetapi juga meningkatkan kemungkinan bahwa pengoptimal kueri akan mendapatkan kesalahan (dan kueri yang dioptimalkan dengan buruk bisa menjadi sangat lambat).
Brendan Long
1
Baru-baru ini saya dihadapkan pada masalah yang sama, karena tabel MySQL InnoDB memiliki batas panjang yang relatif kecil (~ 8000 byte). Dalam tabel masalah saya (data dari formulir asuransi yang sangat panjang, lebih dari 100 kolom) kami memiliki beberapa kolom varchar, semuanya UTF8. Jadi kami dengan mudah memenuhi batas ~ 8000 byte dan mendapatkan "kesalahan 139 dari mesin penyimpanan" setiap saat. Jadi kami harus membagi meja. (Kami menguji dengan format Barracuda yang lebih baru dan berfungsi tanpa membelah, tetapi server klien kami masih menggunakan MySQL 5.0).
MV.
12

Satu meja besar seringkali merupakan pilihan yang buruk. Tabel terkait adalah apa yang database relasional dirancang untuk digunakan. Jika Anda mengindeks dengan benar dan tahu cara menulis kueri yang berkinerja baik, mereka akan bekerja dengan baik.

Saat tabel mendapatkan terlalu banyak kolom, Anda dapat mengalami masalah dengan ukuran sebenarnya dari halaman tempat database menyimpan informasi. Entah rekaman bisa menjadi terlalu besar untuk halaman, di mana Anda mungkin akhirnya tidak bisa membuat atau memperbarui rekaman tertentu yang membuat pengguna tidak senang atau Anda mungkin (di SQL Server setidaknya) dibiarkan meluap untuk tertentu datatypes (dengan sekumpulan aturan yang perlu Anda cari jika Anda melakukan ini) tetapi jika banyak rekaman akan melebihi ukuran halaman, Anda dapat membuat masalah kinerja yang parah. Sekarang bagaimana MYSQL menangani halaman dan apakah Anda memiliki masalah ketika ukuran halaman potensial menjadi terlalu besar adalah sesuatu yang harus Anda cari di dokumentasi untuk database itu.

HLGEM
sumber
1
Ah suara yang berbeda! Itu selalu bagus. Terima kasih atas informasi Anda! Saya akan memastikan bahwa saya menyadarinya ketika saya membuat tabel saya ... tetapi saya tidak tahu saya harus menyadari hal-hal tingkat rendah seperti itu pada awalnya.
Xavier_Ex
4

Saya punya contoh yang bagus. Database yang terlalu dinormalisasi dengan kumpulan hubungan berikut ini:

people -> rel_p2staff -> staff

dan

people -> rel_p2prosp -> prospects

Jika orang memiliki nama dan detail orang, staf hanya memiliki detail catatan staf, prospek hanya memiliki detail prospek, dan tabel rel adalah tabel hubungan dengan kunci asing dari orang yang menautkan ke staf dan prospek.

Desain semacam ini berlaku untuk seluruh database.

Sekarang untuk membuat kueri kumpulan relasi ini, itu adalah penggabungan multi-tabel setiap waktu, terkadang 8 tabel dan lebih bergabung. Ini telah berfungsi dengan baik hingga pertengahan tahun ini, ketika mulai menjadi sangat lambat sekarang setelah kami melewati 40000 catatan orang.

Pengindeksan dan semua buah gantung rendah telah digunakan tahun lalu, semua kueri dioptimalkan untuk kesempurnaan. Ini adalah akhir dari jalan untuk desain normalisasi tertentu dan manajemen sekarang menyetujui pembangunan kembali seluruh aplikasi yang bergantung padanya serta restrukturisasi database, selama jangka waktu 6 bulan. $$$$ Aduh.

Solusinya adalah memiliki hubungan langsung untuk people -> staffdanpeople -> prospect

Vlad
sumber
Apakah tertarik untuk mengetahui bagaimana pembangunan kembali berlangsung? Apakah Anda akhirnya merancang sesuatu yang mirip dengan pewarisan tabel tunggal di mana Anda pernah typemenjadi staffatau prospect?
Coderama
1
Pergi dengan orang-orang yang berhubungan langsung -> staf dan orang -> calon pelanggan, sangat menarik, mudah digunakan, cepat untuk ditanyakan.
Vlad
4

Menemukan ini, dan sebagai seseorang yang dulu sering menggunakan MySQL, dan kemudian beralih ke Postgres baru-baru ini, salah satu keuntungan besarnya adalah Anda dapat menambahkan objek JSON ke bidang di Postgres.

Jadi jika Anda berada dalam situasi ini, Anda tidak harus memutuskan antara satu tabel besar dengan banyak kolom dan membaginya, tetapi Anda dapat menggabungkan kolom menjadi objek JSON untuk menguranginya, misalnya alamat menjadi 5 kolom, itu bisa saja jadilah satu. Anda juga dapat melakukan kueri pada objek itu.

moinhaque.dll
sumber
Bagaimana dengan performanya saat menggunakan objek json saat query?
dagalti
1
@dagalti kinerjanya baik-baik saja untuk aplikasi yang telah saya gunakan. Saya belum melakukan benchmarking saya sendiri, tapi ini mungkin berguna bagi Anda: arangodb.com/2018/02/…
moinhaque
3

tanyakan pada diri Anda pertanyaan-pertanyaan ini jika Anda meletakkan semuanya dalam satu tabel, apakah Anda akan memiliki beberapa baris untuk pengguna itu? Jika Anda harus memperbarui pengguna, apakah Anda ingin menyimpan jejak audit? Bisakah pengguna memiliki lebih dari satu contoh elemen data? (seperti nomor telepon misalnya) akankah Anda memiliki kasus di mana Anda mungkin ingin menambahkan elemen atau serangkaian elemen nanti? jika Anda menjawab ya maka kemungkinan besar Anda ingin memiliki tabel anak dengan hubungan kunci asing.

Kelebihan tabel induk / anak adalah integritas data, kinerja melalui indeks (ya, Anda juga dapat melakukannya pada tabel datar) dan IMO lebih mudah dipelihara jika Anda perlu menambahkan bidang nanti, terutama jika itu akan menjadi bidang yang diperlukan.

Desain kontra lebih sulit, kueri menjadi sedikit lebih kompleks

Tetapi, ada banyak kasus di mana satu meja datar besar akan sesuai sehingga Anda harus melihat situasi Anda untuk memutuskan.

Brian
sumber
Terima kasih telah mengingatkan saya! Jadi dalam kasus saya, saya hanya mempertimbangkan kasus di mana setiap pengguna tidak dapat memiliki lebih dari satu baris sehingga semua bidang informasi adalah satu-ke-satu. Juga pengguna tidak dapat memiliki lebih dari satu contoh dari elemen yang sama seperti yang saya percaya dalam konsep satu elemen tidak dapat ada di lebih dari satu tempat. Untuk pertanyaan ketiga, ya saya mungkin menambahkan lebih banyak elemen ke tabel tetapi mereka tidak akan melanggar persyaratan yang saya sebutkan di atas. Saya pikir tabel induk / anak bagus ketika saya ingin mengasosiasikan beberapa baris ke satu pengguna, tetapi dalam hal ini perhatian saya adalah bahwa pengguna memiliki banyak kolom satu-ke-satu.
Xavier_Ex
bahkan jika semua elemen saat ini adalah satu ke satu, itu tidak menghilangkan kebutuhan atau keinginan untuk memiliki tabel induk / anak IMO. Menyimpan log data yang diubah adalah salah satu kegunaan. objek lazy loading adalah hal lain. sementara ada manfaat untuk satu struktur tabel, ada juga manfaat untuk tata letak orang tua anak (meskipun saya telah melihat orang-orang bertindak ekstrem dengan ini juga).
Brian
1

Saya sudah selesai melakukan semacam desain database. bagi saya, itu tergantung pada kesulitan sistem dengan manajemen database; ya memang benar memiliki data unik di satu tempat saja tetapi sangat sulit untuk membuat kueri dengan database yang terlalu dinormalisasi dengan banyak catatan. Cukup gabungkan dua skema; gunakan satu tabel besar jika Anda merasa akan memiliki catatan besar yang sulit dipertahankan seperti facebook, gmail, dll. dan menggunakan tabel yang berbeda untuk satu set record untuk sistem yang sederhana ... nah ini hanya pendapat saya .. saya harap ini bisa membantu .. lakukan saja .. Anda bisa melakukannya ... :)

Christopher
sumber
1
"gunakan satu tabel besar jika Anda akan memiliki catatan yang sangat besar .." Tapi Facebook, Google tidak menyimpan data pengguna dalam satu tabel, mereka memisahkannya sebanyak tabel.
Yami Odymel
0

Cara konvensional untuk melakukan ini adalah dengan menggunakan tabel yang berbeda seperti pada skema bintang atau skema kepingan salju. Namun, saya akan mendasarkan strategi ini menjadi dua kali lipat. Saya percaya pada teori bahwa data seharusnya hanya ada di satu tempat, karena skema yang saya sebutkan akan berfungsi dengan baik. Namun, saya juga percaya bahwa untuk mesin pelaporan dan suite BI, pendekatan kolumnar akan sangat bermanfaat karena lebih mendukung kebutuhan pelaporan. Pendekatan kolom seperti yang ada di infobright.org memiliki peningkatan kinerja dan kompresi yang sangat besar yang menjadikan penggunaan kedua pendekatan ini sangat berguna. Banyak perusahaan mulai menyadari bahwa hanya memiliki satu arsitektur database dalam organisasi tidak mendukung seluruh kebutuhan mereka. Banyak perusahaan yang menerapkan kedua konsep memiliki lebih dari satu arsitektur database.

Craig Trombly
sumber
Terima kasih atas informasinya, tapi maaf saya tidak begitu mengerti jawaban Anda ... Saya akan melakukan pencarian pada dua skema yang Anda sebutkan pertama ...
Xavier_Ex
-4

Saya pikir memiliki satu tabel lebih efektif tetapi Anda harus memastikan bahwa tabel diatur sedemikian rupa sehingga menunjukkan hubungan, tren serta perbedaan variabel dari baris yang sama. misalnya jika tabel menunjukkan usia dan nilai siswa, Anda harus menyusun tabel sedemikian rupa sehingga terima kasih skor tertinggi dapat dibedakan dengan baik dengan skor terendah dan perbedaan usia siswa genap.

pengguna8081853
sumber