Apakah menyimpan daftar string dalam bidang basis data tunggal adalah ide yang buruk? Mengapa?


14

Baru-baru ini, saya mulai bekerja pada beberapa sistem warisan. Orang-orang yang mengembangkannya, datang ke ide untuk menyimpan daftar string dalam bidang tunggal dari tabel database. Katakanlah itu adalah pengidentifikasi untuk objek yang tidak memiliki representasi atau data dalam database. Kisaran pengidentifikasi itu akan relatif kecil dalam produksi.

Di sisi lain, intuisi saya dan "selera desain yang bagus" memberi tahu saya bahwa itu harus diwakili dalam tabel terpisah (mirip dengan meja yang digunakan untuk mewakili banyak-ke-banyak hubungan).

Apakah pendekatan mereka benar-benar buruk dan akan lebih baik untuk memulai refactoring? Jika ya, konsekuensi buruk apa yang dapat ditimbulkan oleh desain asli di masa depan? Apakah ada prinsip desain relasional yang menjelaskan pendekatan itu?

Edit untuk menanggapi komentar:

Seperti yang saya duga, mereka tidak menggunakan pendekatan ini untuk menyelesaikan beberapa masalah khusus seperti penataan hierarkis dengan cara yang rumit. Skenario yang paling mungkin adalah mereka hanya bekerja di bawah tekanan waktu dan perlu mengimplementasikan fitur baru secepat mungkin.

Saya yakin bahwa sebelumnya bidang mewakili nilai tunggal. Mereka akan mengimplementasikan fitur untuk menyimpan lebih dari satu nilai dan mencoba menghindari migrasi basis data.


7
Apakah itu pendekatan yang buruk atau tidak tergantung pada masalah apa yang coba dipecahkannya, dan seberapa baik ia menyelesaikannya. Bisakah Anda memberikan informasi yang lebih spesifik tentang itu?
Robert Harvey

1
Ini hanya menjadi masalah jika Anda ingin menanyakan daftar atau menghapus laporan dari daftar. Jika itu adalah persyaratan, maka mungkin diperlukan pendekatan yang lebih relasional. Jika itu hanya kegigihan, seharusnya menjadi masalah besar.
Jon Raynor

2
Bahkan jika itu adalah hal yang 'tepat' untuk dilakukan, saya tidak akan memulai refactoring sampai Anda mendapatkan persyaratan baru yang memerlukan sesuatu yang tidak dapat diakomodasi oleh strategi ini, seperti kebutuhan untuk pengindeksan cepat pada item koleksi.
Graham

Pembaruan untuk kolom semacam itu juga dapat menimbulkan masalah.

1
@ graham persyaratan baru adalah: "hei kita perlu kueri yang berfungsi dengan ini". Dengan membangun di atas ini, dan tidak membunuhnya segera, Anda benar-benar membuat lebih sulit untuk menyingkirkan dan melakukan hal yang benar. Masalahnya adalah Anda masih dapat menyelesaikan sebagian besar hal dengan strategi ini: PILIH * DARI Produk SEBAGAI GABUNGAN Akun SEBAGAI ON.pount_id REGEXP '[[: <:]]' || a.account_id || '[[:>:]]' WHERE p.product_id = 123;
Pieter B

Jawaban:


16

Datamodel tidak dinormalisasi; untuk jadi itu akan membutuhkan tabel terpisah seperti yang Anda katakan. Dalam hal itu, itu bukan praktik datamodelling yang sangat baik.

Apakah itu dilakukan untuk alasan yang baik atau tidak sulit untuk ditentukan. Dapat dibayangkan, pengkodean penyederhanaan atau kinerja mungkin merupakan motivator. Kemungkinannya adalah bahwa bidang awalnya berisi satu pengidentifikasi, persyaratan berubah dan pengembang tidak punya waktu atau kecenderungan untuk faktor ulang.

Mungkin yang lebih penting adalah apakah Anda harus memperbaiki diri atau tidak. Dalam keadaan yang serupa, saya tidak akan secara langsung menolak kasus seperti ini secara default. Saya akan mempertimbangkannya jika salah satu dari yang berikut ini diterapkan:

  1. Anda memiliki bukti bahwa ini menyebabkan masalah, misalnya dari log masalah lama
  2. Anda tahu pasti bahwa Anda akan membuat perubahan fungsional di bidang itu
  3. kode yang menangani data sangat kompleks dan sulit dipikirkan.

Apa yang akan saya lakukan, dan TBH saya akan merekomendasikan ini setiap kali Anda mengambil alih aplikasi warisan, adalah memulai wiki (atau setara) dan mendokumentasikan kasus-kasus seperti ini. Sebagai contoh,

  • masalah yang Anda temukan seperti kerutan datamodelling
  • perubahan yang Anda rencanakan untuk diterapkan
  • perubahan yang Anda tidak rencanakan untuk diterapkan tetapi akan jika ada waktu
  • bidang kode yang sulit dipikirkan
  • area kode yang sulit Anda pertahankan.

Saya telah menemukan bahwa ini adalah memo ajudan yang berguna bagi saya ketika saya bekerja di dan / atau kembali ke basis kode. Ini juga bisa sangat membantu penerus Anda ketika mereka, pada gilirannya, perlu mulai mempelajari basis kode.


10

Apakah menyimpan daftar string dalam bidang basis data tunggal adalah ide yang buruk?

Ini umumnya akan dianggap sebagai pelanggaran normalisasi.

Namun, kadang-kadang ini digunakan solusi untuk masalah, misalnya dalam penataan hierarkis, di mana string jalur panjang variabel semacam mewakili struktur.

Di antara masalah dengan daftar item dalam satu string dapat berupa:

  • dalam kueri, ini berarti menggunakan pencarian string bukan kalkulus relasional; pengindeksan data bisa bermasalah.
  • ada pertanyaan tentang arti urutan entri dalam daftar, dan Anda kemungkinan besar tidak dapat memaksakan apapun pada pemesanan sebagai kendala pada db.
  • ada masalah karakter pemisah, dan potensi untuk karakter yang lolos / tidak lepas dari masalah dengan masing-masing item.
  • ada potensi untuk entri duplikat dalam daftar yang sama; sekali lagi ini berasal dari tidak dapat langsung menegakkan kendala (meskipun mungkin fungsi pemicu dapat memeriksa kendala).
  • satu item saja masih merupakan daftar, tetapi mungkin keliru karena kita tidak dapat memberi tahu (atau bertanya) database bahwa tipe sebenarnya adalah daftar. Ini bisa menjadi masalah jika sebagian besar baris hanya memiliki satu item dalam daftar, ketika beberapa memiliki lebih dari satu: tidak ada cara untuk menegakkan penggunaan kolom yang benar sebagai daftar.

3

Ini adalah antipattern umum untuk melakukan ini.

Persyaratan Anda berubah dan sekarang Anda membutuhkan lebih banyak nilai di tempat yang dulu hanya membutuhkan nilai. Seperti buku, hanya punya satu penulis, bukan? Siapa yang dapat menduga bahwa sebuah buku memiliki banyak penulis? Ini adalah cara mudah untuk memenuhi perubahan persyaratan ini tanpa harus mengubah skema basis data Anda.

Ada beberapa kelemahannya.

  • Kueri menjadi lebih sulit karena sekarang Anda telah mengidentifikasi data yang digabungkan dalam 1 bidang.
  • Anda tidak dapat lagi menggunakan "=" tetapi harus menggunakan sesuatu seperti "seperti". Yang akan mematikan kinerja.
  • Anda kehilangan kemampuan untuk bergabung di bidang itu.
  • Coba hitung / jumlahkan dll, itu tidak akan berhasil.
  • Memperbarui, menjadi canggung.
  • Anda mendapatkan batas artifisial karena Anda memilih varchar (10) untuk menyimpan daftar commaseparated Anda.
  • dan lainnya.

Jadi pada dasarnya, tolong jangan lakukan ini.

Pada dasarnya Anda mengambil "relasional" dalam "database relasional".


0

Ada banyak argumen untuk menjadi ide yang buruk. Saya pikir akan adil untuk menambahkan beberapa alasan mengapa itu akan menjadi ide yang bagus, atau setidaknya OK. Tidak yakin berapa banyak dari ini berlaku dalam kasus khusus, tetapi tampaknya setidaknya pernyataan kinerja yang dilakukan relevan:

  • jika jumlah dan panjang string sangat terbatas, maka perbedaan kinerja harus diabaikan. Setidaknya untuk beberapa kasus tepi, kinerjanya akan lebih baik, karena Anda tidak perlu bergabung.
  • tergantung pada penggunaan utama bidang ini, formulir ini mungkin lebih mudah ditangani.
  • jika daftar dipesan, dan data tidak memerlukan kunci asing, bidang daftar jauh lebih unggul dari apa pun yang dapat disediakan oleh basis data relasional dalam hal ini.
  • menjadi dukungan piggy sederhana pada bidang tunggal yang ada mungkin menjadi pilihan yang bijaksana dalam sistem di mana migrasi skema mahal. Ini memang utang teknis, tetapi mungkin merupakan jenis yang layak untuk diambil dan tidak pernah dibayar kembali, bahkan jika Anda perlu menghabiskan beberapa bunga sekarang dan kemudian.

Ketika mencoba refactoring, itu selalu merupakan ide yang baik untuk terlebih dahulu memahami alasan di balik pilihan desain sebelumnya. Pastikan bahwa kondisi dan persyaratan memang cukup berubah untuk menjamin biaya dan risiko.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.