Selama pertemuan mingguan terakhir kami, seseorang yang tidak memiliki pengalaman latar belakang dalam Administrasi Database mengajukan pertanyaan ini:
"Apakah akan ada skenario yang membenarkan penyimpanan data in-line (string) alih-alih beberapa baris?"
Mari kita asumsikan tabel yang disebut countryStates
tempat kita ingin menyimpan negara bagian; Saya akan menggunakan USA untuk contoh ini dan tidak akan mencantumkan semua Negara demi kemalasan.
Di sana kita akan memiliki dua kolom; yang satu dipanggil Country
dan yang lainnya dipanggil States
. Seperti yang dibahas di sini , dan diusulkan oleh jawaban @ srutzky , PK
kode tersebut akan ditentukan oleh ISO 3166-1 alpha-3 .
Meja kami akan terlihat seperti ini:
+---------+-----------------------+-------------------------------------------------------+
| Country | States | StateName |
+---------+-----------------------+-------------------------------------------------------+
| USA | AL, CA, FL,OH, NY, WY | Alabama, California, Florida, Ohio, New York, Wyoming |
+---------+-----------------------+-------------------------------------------------------+
Ketika mengajukan pertanyaan yang sama kepada pengembang teman, ia mengatakan bahwa dari sudut pandang ukuran lalu lintas data, ini mungkin berguna, tetapi tidak jika kita perlu memanipulasi data ini. Dalam hal ini harus ada intelijen pada kode aplikasi yang dapat mengubah string ini dalam daftar (misalkan perangkat lunak yang memiliki akses ke tabel ini perlu membuat kotak kombo).
Kami menyimpulkan bahwa model ini tidak terlalu berguna, tetapi saya curiga bahwa mungkin ada cara untuk membuat ini berguna.
Yang ingin saya tanyakan adalah apakah ada di antara Anda yang sudah melihat, mendengar atau melakukan sesuatu seperti ini dengan cara yang benar-benar berfungsi .
sumber
a;b;c
, gunakan ujung depan untuk mengurai string Anda Anda kemudian mendapatkana
,b
,c
dan membawa pada eksekusi melakukan sesuatu dengan mereka, mungkin ?. Merasa itu mungkin cocok dengan semacam kebutuhan spesifik dengan cara itu ... Setelah dipikir-pikir, tidak. Anda selalu dapat menyimpan ID, Gabung tabel Anda dan buat string gabungan daripada yang dapat mengirim konten ke FE ...Jawaban:
Untuk memulainya, judul Pertanyaan saat ini yang mengacu pada "menyimpan data sebagai string, bukan kolom" agak membingungkan. Ketika berbicara tentang menyimpan data sebagai string, bukan sesuatu yang lain, itu biasanya merujuk pada serialisasi segalanya ke format string, bukan tipe data yang benar / kuat (misalnya
INT
atauDATETIME
). Tetapi jika bertanya tentang menyimpan data sebagai beberapa nilai dalam satu bidang sebagai lawan dari baris terpisah, itu sedikit berbeda. Dan agar adil, sementara nilai-nilai gabungan paling mudah dilakukan dengan string, itu juga dapat dilakukan denganINT
danBINARY
mengetik juga, baik dengan sedikit-masking atau dengan cara yang sama memesan posisi tertentu untuk memiliki makna yang berbeda. Karena interpretasi kedua adalah apa yang sebenarnya ditanyakan, berdasarkan pada teks Pertanyaan, mari kita bahas itu.Dengan kata lain: Tidak. Jika Anda menyimpan poin data aktual maka itu hanya akan menimbulkan rasa sakit (dalam hal kode dan kinerja) karena merupakan komplikasi yang tidak perlu. Jika itu adalah nilai yang hanya akan disimpan sebagai satu unit, diperbarui sebagai satu unit, dan tidak pernah dibongkar dalam basis data, maka itu bisa ok karena secara analog sama dengan menyimpan gambar atau PDF. Jika tidak, setiap upaya untuk mengurai data akan tidak valid menggunakan indeks apa pun (misalnya menggunakan
LIKE '%something%'
, atauCHARINDEX
, atauPATINDEX
, atauSUBSTRING
, dll).Jika Anda perlu menyimpan nilai terpisah dalam bidang tunggal dari satu baris, maka ada cara yang lebih tepat untuk melakukan itu: XML atau JSON. Ini adalah format yang dapat diuraikan ( XML / JSON ) dan XML bahkan dapat diindeks . Namun idealnya data ini akan disimpan dalam bidang yang diketik dengan benar sehingga dapat benar-benar bermanfaat.
Dan jangan lupa bahwa tujuan RDBMS adalah untuk menyimpan data sedemikian rupa sehingga dapat diambil dan dimanipulasi seefisien mungkin, dalam batasan yang ditentukan oleh kepatuhan ACID . Mengambil nilai-nilai gabungan cukup buruk karena kebutuhan untuk menguraikan nilai-nilai terlebih dahulu, dan itu tidak dapat diindeks. Tetapi memanipulasi sering kali berarti mengganti seluruh gumpalan hanya untuk memperbarui bagiannya (dengan asumsi tidak ada pola yang digunakan dengan
REPLACE
fungsi). Tipe data XML setidaknya memungkinkan untuk XML DML untuk pembaruan sederhana, meskipun itu masih tidak secepat pembaruan sederhana dari data yang dimodelkan dengan benar.Juga, mengingat skenario seperti apa yang diperlihatkan dalam Pertanyaan di atas, dengan menggabungkan semua Kode Negara bersama-sama, Anda tidak akan dapat dengan Foreign Key (dalam arah mana pun) nilai-nilai itu.
Dan bagaimana jika persyaratan bisnis berubah seiring waktu dan Anda perlu melacak properti tambahan dari barang-barang ini? Dalam hal "negara bagian", bagaimana dengan ibu kota, atau populasi, atau pengurutan, atau yang lainnya? Disimpan dengan benar sebagai baris, Anda dapat menambahkan lebih banyak kolom untuk properti tambahan. Tentu, Anda dapat memiliki beberapa tingkat data yang dapat diuraikan, seperti
|StateCode,Capital,Population |StateCode,Capital,Populate|...
tetapi semoga siapa pun dapat melihat masalah tersebut tumbuh secara eksponensial di luar kendali. Tentu saja, masalah khusus ini agak mudah ditangani dengan format XML dan JSON, dan itulah nilainya seperti yang disebutkan di atas. Tetapi Anda masih membutuhkan alasan yang sangat baik untuk menggunakan salah satu dari mereka sebagai sarana awal pemodelan karena tidak akan pernah seefisien menggunakan bidang diskrit dalam baris terpisah.sumber
Saya sebenarnya menggunakan sesuatu seperti itu untuk tujuan yang sangat terbatas. Kami membuat tabel header untuk file output. Mereka secara khusus dibangun dan sebagian besar hanya judul kolom tetapi tidak cukup. Jadi datanya terlihat seperti
Pada dasarnya itu tampak seperti daftar yang dibatasi. Dan dalam satu cara itu. Tetapi untuk tujuan kami, itu adalah string panjang tunggal.
Itulah triknya di sini. Jika Anda tidak pernah berencana untuk menguraikan daftar maka ada baiknya menyimpan daftar. Namun jika Anda akan atau bahkan mungkin perlu menguraikan daftar maka layak ruang ekstra & waktu untuk membaginya dan menyimpannya dalam baris terpisah.
sumber
Saya pernah menggunakannya sekali dengan meja yang agak kecil, misalnya:
Dan kemudian menyimpan nilai
CRM,SMS,SELF-CARE
- nilaivalid_channel
.Seluruh tabel memiliki sekitar 10 catatan.
valid_channel
berisi nilai-nilai yang seharusnya berada dalam tabel tautan yang menggambarkan hubungan banyak-ke-banyak. Mejat1
tidak akan digunakan secara intensif, jadi kami memutuskan untuk menyusuri jalan ini. Namun, beberapa politik terlibat dalam keputusan ini (lihat di bawah).Tetapi secara umum saya menghindarinya, ini bukan 3NF.
Tempat saya bekerja saat ini memiliki lusinan kolom seperti itu di semua tempat. Pembenaran mereka adalah bahwa itu membuat kueri mereka lebih mudah: alih-alih bergabung dengan tiga tabel menggunakan tabel penautan mereka bisa langsung menggunakan tabel definisi
LIKE
. Misalnya+ Mengerikan pada Oracle menonaktifkan penggunaan indeks karena memulai
'%,'
.sumber
LIKE
atau gabung sederhana?LIKE
akan lebih lambat, terutama jika data dimodelkan dengan benar untuk menggunakanTINYINT
bidang PK dichannel_def
. Maka itu hanya perlu membandingkan satu byte antara dua tabel. Di sini ia harus mengurai string, karakter demi karakter (setidaknya sampai kondisi terpenuhi), dan sedang melakukan pencarian case-insensitive (berdasarkan tabel yang diberikan def tidak menunjukkan_BIN2
collation sedang digunakan). Ini juga membatalkan indeks pada SQL Server. Saya menjawab ini dengan jawaban saya dengan mengatakan bahwa parsing tidak dapat menggunakan indeks. Saya baru saja memperbarui jawaban saya untuk membuatnya lebih jelas.LIKE
klausa dan menghasilkan hasil yang aneh, itu masih dapat menyebabkan masalah lain atau setidaknya membuat debugging lebih sulit / lebih lama). Itu juga membuat memperbaruivalid_channels
bidang lebih rumit. Ini bukan untuk mengatakan bahwa ini tidak bekerja, hanya ada ada yang baik alasan untuk melakukannya.Ini dilakukan di sini di SE. Seperti Marc Gravell menulis :
"Format baru" ini adalah langkah selanjutnya dari "format lama" yang sedikit berbeda dan dipilih untuk menggunakan fitur Pencarian Penuh Teks SQL Server, sehingga beberapa manfaat tidak relevan jika Anda melakukannya dari awal.
Mereka mungkin tidak sepenuhnya menormalkan hal itu karena jumlah pekerjaan dan alasan kinerja.
sumber
Nah, salah satu kemungkinan manfaat utama menggunakan string, dan tipe data lainnya, adalah mengirimkannya dari SQL Server ke C #, C, C ++ (dll) menggunakan SQLCLR ketika kinerja semata mungkin diperlukan. Anda bahkan dapat membuat tampilan atau prosedur tersimpan untuk merepresentasikan data relasional secara non-relasional - seperti Anda menggunakan contoh di atas untuk tujuan ini.
Lihat contoh ini:
http://aboutsqlserver.com/2013/07/22/clr-vs-t-sql-performance-considerations/
per Wikipedia: SQL CLR atau SQLCLR (SQL Common Language Runtime) adalah teknologi untuk hosting mesin runtime bahasa umum Microsoft .NET dalam SQL Server. SQLCLR memungkinkan kode terkelola dihosting oleh, dan dijalankan di, lingkungan Microsoft SQL Server.
sumber
Dalam pandangan saya, jawabannya adalah tidak. Saya tidak menggunakan pendekatan ini dan akan menghindarinya - saya tidak bisa memikirkan alasan mengapa saya menempuh rute itu. Anda condong ke dunia JSON / NoSQL dengan sebuah array.
Kami memiliki pilihan desain yang serupa dalam peran sebelumnya di mana tim arsitek ingin memiliki bidang "Data" yang dibatasi dan kemudian dikonversi ke biner. Kami tidak turun rute pada akhirnya karena beberapa alasan.
Jika Anda harus bergabung dengan tipe data ini, itu akan menjadi pengalaman yang buruk. Memperbarui elemen tunggal dari string juga tidak menyenangkan.
sumber