Saya mendekati proyek di mana saya harus mengimplementasikan database dengan bos saya; kami adalah permulaan yang sangat kecil sehingga lingkungan kerja sangat pribadi.
Dia telah memberi saya salah satu database perusahaan sebelumnya dan itu benar-benar bertentangan dengan apa yang saya diajarkan (dan baca tentang) di sekolah untuk RDBMS. Misalnya, ada seluruh basis data di sini yang terdiri dari satu tabel (per basis data independen). Salah satu tabel itu adalah 20+ kolom dan untuk konteks, berikut adalah beberapa nama kolom dari satu tabel:
lngStoreID | vrStoreName | lngPerusahaanID | vrCompanyName | lngProductID | vrProductName
Intinya adalah bahwa di mana ia harus memiliki tabel individual yang menyimpan data entitas (nama, ukuran, tanggal pembelian, dll.) Ia menyodorkan semuanya dalam satu tabel besar per basis data.
Saya ingin meningkatkan desain ini, tetapi saya tidak yakin mengapa model data yang dinormalisasi dan tersegmentasi dengan baik akan benar-benar meningkatkan produk ini. Sementara saya terbiasa dengan desain database dari perguruan tinggi dan saya mengerti bagaimana melakukannya, saya tidak yakin mengapa ini benar-benar meningkatkan database.
Mengapa skema relasional yang baik meningkatkan database?
sumber
He [the boss] had given me one of his databases before and it completely went against what I was taught (and read about) in school for RDBMS
<- Selamat datang di dunia nyata!Jawaban:
Argumen kinerja biasanya merupakan argumen yang paling intuitif. Anda terutama ingin menunjukkan bagaimana akan sulit untuk menambahkan indeks yang baik dalam database yang dinormalisasi secara tidak benar (catatan: ada kasus tepi di mana denormalisasi sebenarnya dapat meningkatkan kinerja, tetapi ketika Anda berdua tidak berpengalaman dengan database relasional Anda kemungkinan besar tidak akan dengan mudah lihat kasus ini).
Lainnya adalah argumen ukuran penyimpanan. Tabel denormalized dengan banyak redudansi akan membutuhkan penyimpanan jauh lebih banyak. Ini juga berperan dalam aspek kinerja: semakin banyak data yang Anda miliki, semakin lambat kueri Anda.
Ada juga argumen yang sedikit lebih sulit untuk dipahami, tetapi sebenarnya lebih penting karena Anda tidak dapat menyelesaikannya dengan melemparkan lebih banyak perangkat keras padanya. Itulah masalah konsistensi data. Basis data yang dinormalisasi dengan benar akan menangani dengan sendirinya bahwa produk dengan ID tertentu selalu memiliki nama yang sama. Tetapi dalam database denormalized, inkonsistensi seperti itu mungkin, jadi perhatian khusus harus diambil ketika datang untuk menghindari inkonsistensi, yang akan memakan waktu pemrograman untuk memperbaikinya dan masih akan menyebabkan bug yang akan membebani Anda dengan kepuasan pelanggan.
sumber
Menggunakan perangkat lunak Manajemen Basis Data khusus mungkin jauh lebih mudah (maaf; tidak bisa menolak).
Jika basis data ini hanya peduli tentang "pencatatan" produk mana yang dijual di mana, kapan dan oleh siapa, maka Anda mungkin dapat meregangkan Definisi "basis data OK" cukup jauh untuk membahasnya. Jika data ini digunakan untuk hal lain, maka itu sangat buruk.
Tapi ...
Apakah aplikasi / pertanyaan yang menggunakan data ini merespons dengan buruk / lambat? Jika tidak, maka tidak ada masalah nyata untuk dipecahkan. Tentu, itu terlihat dan terasa jelek, tetapi jika berhasil maka Anda tidak akan mendapatkan "poin" untuk menyarankannya "bisa" lebih baik.
Jika Anda dapat menemukan gejala yang pasti (yaitu masalah) yang sepertinya disebabkan oleh pemodelan data yang buruk, maka buat prototipe solusi yang lebih baik. Ambil salinan salah satu dari "basis data" ini, normalkan data dan lihat apakah solusi Anda berjalan lebih baik. Jika jauh lebih baik (dan saya sepenuhnya berharap bahwa setiap operasi pembaruan pada data ini akan ditingkatkan secara besar - besaran ) maka kembalilah ke atasan Anda dan tunjukkan pada mereka peningkatannya.
Sangat mungkin untuk membuat kembali "tampilan tabel tunggal" dari data dengan .. well .. Views.
sumber
Jawabannya adalah: itu tidak selalu meningkatkan database. Anda harus menyadari bahwa apa yang Anda mungkin ajarkan disebut Bentuk Normal Ketiga .
Formulir lain valid dalam beberapa situasi, yang merupakan kunci untuk menjawab pertanyaan Anda. Contoh Anda terlihat seperti Bentuk Normal Pertama , jika itu membantu Anda merasa lebih baik tentang keadaan saat ini.
Aturan 3NF membangun hubungan di antara data yang "meningkatkan" database:
Mencegah data yang tidak valid masuk ke sistem Anda (jika suatu hubungan 1-ke-1 itu memaksa kesalahan meskipun kode tertulis di atasnya). Jika data Anda konsisten dalam basis data, kecil kemungkinannya akan menghasilkan inkonsistensi di luar basis data Anda.
Ini memberikan cara untuk memvalidasi kode (misalnya hubungan banyak ke satu adalah sinyal untuk membatasi properti / perilaku objek). Saat menulis kode untuk menggunakan database, terkadang programmer memperhatikan struktur data sebagai indikator bagaimana kode mereka seharusnya bekerja. Atau mereka dapat memberikan umpan balik yang bermanfaat jika database tidak cocok dengan kode mereka. (Sayangnya, ini lebih seperti angan-angan.)
Berikan aturan yang dapat secara signifikan membantu Anda mengurangi kesalahan saat membangun database, sehingga Anda tidak membangunnya berdasarkan persyaratan sewenang-wenang yang mungkin datang kapan saja selama masa database. Sebaliknya, Anda secara sistematis mengevaluasi informasi untuk mencapai tujuan tertentu.
Struktur basis data yang tepat mengarah pada peningkatan kinerja dengan menghubungkan data dengan cara yang meminimalkan penyimpanan data, meminimalkan panggilan penyimpanan untuk mengambil data, memaksimalkan sumber daya dalam memori dan / atau meminimalkan penyortiran / manipulasi data untuk dataset tertentu yang Anda miliki, dibandingkan dengan permintaan Anda mengeksekusinya. Tetapi struktur "benar" tergantung pada jumlah data, sifat data, jenis kueri, sumber daya sistem, dll. Dengan normalisasi Anda dapat membuat kinerja lebih buruk (yaitu jika Anda memuat semua data sebagai 1 tabel - bergabung dengan dapat memperlambat sebuah permintaan). Pemrosesan transaksi (OLTP) vs intelijen bisnis (data warehouse) sangat berbeda.
Di perusahaan kecil dengan kumpulan data kecil, Anda mungkin menemukan bahwa tidak ada yang salah dengan keadaannya sekarang. Kecuali, jika Anda tumbuh, akan sulit untuk "memperbaikinya" nanti, karena saat tabel bertambah besar, sistem yang menggunakannya kemungkinan akan semakin lambat.
Biasanya Anda akan ingin menekankan transaksi cepat saat perusahaan tumbuh. Namun, jika Anda menghabiskan waktu untuk proyek ini sekarang alih-alih hal-hal lain yang mungkin perlu perusahaan lebih mendesak, Anda mungkin tidak pernah memiliki masalah itu karena perusahaan Anda tidak pernah benar-benar tumbuh. Itulah "tantangan pra-optimasi" - tempat untuk menghabiskan waktu berharga Anda sekarang.
Semoga berhasil!
sumber
WHERE
klausa. Tentu saja, ini masih bisa salah, tetapi kecil kemungkinannya dalam situasi normal karena Anda hanya perlu mencocokkan satu baris melalui kunci primer.Ada beberapa alasan mengapa menggunakan satu "meja dewa" besar itu buruk. Saya akan mencoba dan mengilustrasikan masalah dengan database contoh yang dibuat. Anggaplah Anda mencoba membuat model acara olahraga. Kami akan mengatakan Anda ingin membuat model game dan tim yang bermain di game-game itu. Desain dengan beberapa tabel mungkin terlihat seperti ini (ini sengaja disederhanakan jadi jangan terjebak di tempat-tempat di mana lebih banyak normalisasi dapat diterapkan):
dan database tabel tunggal akan terlihat seperti ini
Pertama, mari kita lihat membuat indeks pada tabel tersebut. Jika saya membutuhkan indeks di kota asal untuk tim, saya bisa menambahkannya ke
Teams
tabel atauTeamsAndGames
tabel dengan mudah. Ingat bahwa setiap kali Anda membuat indeks, yang perlu disimpan di disk di suatu tempat dan diperbarui saat baris ditambahkan ke tabel. Dalam halTeams
tabel ini cukup mudah. Saya memasukkan tim baru, basis data memperbarui indeks. Tapi untuk apaTeamsAndGames
? Yah, hal yang sama berlaku dariTeams
contoh. Saya menambahkan tim, indeks diperbarui. Tapi itu juga terjadi ketika saya menambahkan game! Meskipun bidang itu akan menjadi nol untuk game, indeks tetap harus diperbarui dan disimpan di disk untuk game itu. Untuk satu indeks, ini kedengarannya tidak terlalu buruk. Tetapi ketika Anda membutuhkan banyak indeks untuk beberapa entitas yang dijejalkan ke dalam tabel ini, Anda membuang banyak ruang untuk menyimpan indeks dan banyak waktu prosesor memutakhirkannya untuk hal-hal yang tidak berlaku.Kedua, konsistensi data. Dalam hal menggunakan dua tabel terpisah, saya bisa menggunakan kunci asing dari
Games
tabel keTeams
tabel untuk menentukan tim mana yang bermain dalam permainan. Dan dengan asumsi saya membuatHomeTeamId
danAwayTeamId
kolom tidak dapat dibatalkan, basis data akan memastikan bahwa setiap permainan yang saya masukkan memiliki 2 tim dan bahwa tim-tim itu ada di basis data saya. Tapi bagaimana dengan skenario tabel tunggal? Nah, karena ada banyak entitas dalam tabel ini, kolom-kolom itu harus nullable (Anda bisa membuatnya tidak nullable dan mendorong data sampah di sana, tapi itu hanya ide yang mengerikan). Jika kolom tersebut tidak dapat dibatalkan, basis data tidak dapat lagi menjamin bahwa ketika Anda memasukkan game, ia memiliki dua tim.Tetapi bagaimana jika Anda memutuskan untuk tetap melakukannya? Anda mengatur kunci asing sedemikian rupa sehingga bidang-bidang itu menunjuk kembali ke entitas lain dalam tabel yang sama. Tetapi sekarang database hanya akan memastikan bahwa entitas-entitas itu ada dalam tabel, bukan bahwa mereka adalah tipe yang benar. Anda bisa dengan mudah mengatur
GameHomeTeamId
ke ID game lain dan database tidak akan mengeluh sama sekali. Jika Anda mencobanya dalam skenario beberapa tabel, basis data akan cocok.Anda dapat mencoba mengurangi masalah ini dengan mengatakan "baiklah, kami hanya akan memastikan bahwa kami tidak pernah melakukannya dalam kode". Jika Anda yakin dengan kemampuan Anda untuk menulis kode bebas bug pertama kali dan dalam kemampuan Anda untuk memperhitungkan setiap kombinasi aneh dari hal-hal yang mungkin dicoba pengguna, silakan saja. Saya pribadi tidak yakin dengan kemampuan saya untuk melakukan hal-hal itu, jadi saya akan membiarkan database memberi saya jaring pengaman ekstra.
(Ini menjadi lebih buruk jika desain Anda adalah di mana Anda menyalin semua data yang relevan di antara baris daripada menggunakan kunci asing. Setiap ejaan / ketidakkonsistenan data lainnya akan sulit untuk diselesaikan. Bagaimana Anda bisa tahu apakah "Jon" adalah salah mengeja dari "John" "Atau jika itu disengaja (karena mereka adalah dua orang yang terpisah)?)
Ketiga, hampir setiap kolom perlu dibatalkan atau harus diisi dengan data yang disalin atau sampah. Gim tidak perlu
TeamName
atauTeamHomeCity
. Jadi setiap game membutuhkan semacam placeholder di sana atau perlu dibatalkan. Dan jika itu nullable, database akan dengan senang hati mengambil game tanpaTeamName
. Ini juga akan membutuhkan tim tanpa nama, bahkan jika logika bisnis Anda mengatakan itu seharusnya tidak pernah terjadi.Ada beberapa alasan lain mengapa Anda ingin tabel terpisah (termasuk menjaga kewarasan pengembang). Bahkan ada beberapa alasan mengapa tabel yang lebih besar mungkin lebih baik (denormalisasi kadang-kadang meningkatkan kinerja). Skenario-skenario itu sedikit dan jarang (dan biasanya paling baik ditangani ketika Anda memiliki metrik kinerja untuk menunjukkan bahwa itu benar-benar masalah, bukan indeks yang hilang atau yang lainnya).
Akhirnya, kembangkan sesuatu yang mudah dipelihara. Hanya karena "berfungsi" tidak berarti tidak apa-apa. Mencoba mempertahankan meja dewa (seperti kelas dewa) adalah mimpi buruk. Anda hanya menyiapkan diri Anda untuk kesakitan nanti.
sumber
Kutipan hari itu: " Teori dan praktik harus sama ... dalam teori "
Tabel dinormalisasi
Tabel hold-it-all unik Anda berisi data yang redundan memiliki satu keuntungan: membuat pelaporan pada barisnya sangat mudah dikodekan dan cepat dijalankan karena Anda tidak harus melakukan penggabungan. Tetapi ini dengan biaya tinggi:
IngCompanyID
danvrCompanyName
). Memperbarui data master mungkin perlu memperbarui lebih banyak baris daripada dalam skema yang dinormalisasi.Meja dinormalisasi
Kerugian di atas adalah keuntungan untuk skema yang dinormalisasi. Tentu saja, pertanyaannya mungkin sedikit lebih rumit untuk ditulis.
Singkatnya, skema yang dinormalisasi mengekspresikan struktur dan hubungan yang lebih baik antara data Anda. Saya akan menjadi provokatif dan mengatakan itu adalah perbedaan yang sama dari antara disiplin yang diperlukan untuk menggunakan satu set laci kantor yang dipesan dan kemudahan penggunaan tempat sampah.
sumber
Saya pikir setidaknya ada dua bagian dari pertanyaan Anda:
1. Mengapa entitas dari tipe yang berbeda tidak disimpan dalam tabel yang sama?
Jawaban paling penting di sini adalah keterbacaan dan kecepatan kode. A
SELECT name FROM companies WHERE id = ?
jauh lebih mudah dibaca daripada aSELECT companyName FROM masterTable WHERE companyId = ?
dan Anda cenderung untuk secara tidak sengaja meminta omong kosong (mis.SELECT companyName FROM masterTable WHERE employeeId = ?
Tidak akan mungkin ketika perusahaan dan karyawan disimpan dalam tabel yang berbeda). Adapun kecepatan, data dari tabel database diambil baik dengan membaca tabel penuh secara berurutan, atau dengan membaca dari indeks. Keduanya lebih cepat jika tabel / indeks mengandung lebih sedikit data, dan itu terjadi jika data disimpan dalam tabel yang berbeda (dan Anda hanya perlu membaca salah satu tabel / indeks).2. Mengapa entitas dari tipe tunggal dipecah menjadi sub-entitas yang disimpan dalam tabel yang berbeda?
Di sini, alasannya adalah sebagian besar untuk mencegah inkonsistensi data. Dengan pendekatan tabel tunggal, untuk sistem manajemen pesanan Anda dapat menyimpan nama pelanggan, alamat pelanggan, dan ID produk dari produk yang dipesan oleh pelanggan sebagai satu kesatuan. Jika pelanggan memesan beberapa produk, Anda akan memiliki beberapa contoh nama dan alamat pelanggan dalam database Anda. Dalam kasus terbaik, Anda baru saja mendapatkan data duplikat di database Anda, yang mungkin memperlambatnya sedikit. Tetapi kasus yang lebih buruk adalah seseorang (atau beberapa kode) melakukan kesalahan ketika data dimasukkan sehingga perusahaan berakhir dengan alamat berbeda di basis data Anda. Ini saja sudah cukup buruk. Tetapi jika Anda menanyakan alamat perusahaan berdasarkan namanya (mis
SELECT companyAddress FROM orders WHERE companyName = ? LIMIT 1
) Anda hanya akan secara sewenang-wenang mendapatkan salah satu dari dua alamat kembali dan bahkan tidak akan menyadari bahwa ada ketidakkonsistenan. Tetapi setiap kali Anda menjalankan kueri, Anda mungkin benar-benar mendapatkan alamat yang berbeda, tergantung pada bagaimana kueri Anda diselesaikan secara internal oleh DBMS. Ini kemungkinan akan merusak aplikasi Anda di tempat lain, dan akar penyebab kerusakan itu akan sangat sulit ditemukan.Dengan pendekatan multi-tabel, Anda akan menyadari bahwa ada ketergantungan fungsional dari nama perusahaan ke alamat perusahaan (jika perusahaan hanya dapat memiliki satu alamat), Anda akan menyimpan tuple (nama perusahaan, alamat perusahaan) dalam satu tabel (mis.
company
), dan (productId, companyName) tuple di tabel lain (misalnyaorder
). SebuahUNIQUE
kendala padacompany
tabel maka bisa menegakkan bahwa setiap perusahaan hanya memiliki satu alamat dalam database Anda sehingga tidak ada inkonsistensi untuk alamat perusahaan yang bisa timbul.Catatan: dalam praktiknya, untuk alasan kinerja Anda mungkin akan menghasilkan companyId unik untuk setiap perusahaan dan menggunakannya sebagai kunci asing alih-alih menggunakan nama perusahaan secara langsung. Tetapi pendekatan umum tetap sama.
sumber
TL; DR - Mereka merancang basis data berdasarkan bagaimana mereka diajarkan ketika mereka masih di sekolah.
Saya bisa menulis pertanyaan ini 10 tahun yang lalu. Butuh beberapa waktu untuk memahami mengapa pendahulu saya mendesain database mereka seperti yang mereka lakukan. Anda bekerja dengan seseorang yang:
Saya tidak menduga itu # 1 karena Anda benar-benar memiliki nomor ID di meja Anda, jadi saya akan menganggap # 2.
Setelah saya keluar dari sekolah, saya bekerja di sebuah toko yang menggunakan AS / 400 (alias IBM i). Saya menemukan beberapa hal aneh dalam cara mereka mendesain database mereka, dan mulai menganjurkan kita membuat perubahan untuk mengikuti bagaimana saya diajarkan bagaimana merancang database. (Saya bodoh saat itu)
Butuh programmer yang lebih tua dan sabar untuk menjelaskan kepada saya mengapa semuanya dilakukan seperti itu. Mereka tidak mengubah skema karena itu akan menyebabkan program yang lebih tua dari saya rusak. Secara harfiah, kode sumber untuk satu program memiliki tanggal pembuatan tahun sebelum saya lahir. Pada sistem yang kami kerjakan, program mereka harus menerapkan semua logika dan operasi yang ditangani oleh perencana kueri basis data Anda. (Anda dapat melihatnya dengan menjalankan EXPLAIN di salah satu pertanyaan Anda)
Dia up-to-date tentang teknik yang saya coba terapkan, tetapi menjaga sistem berjalan lebih penting daripada membuat perubahan "karena itu bertentangan dengan apa yang diajarkan kepada saya". Setiap proyek baru kami mulai memanfaatkan model relasional yang kami bisa. Sayangnya, programmer / konsultan lain dari waktu itu masih mendesain basis data mereka seolah-olah mereka bekerja dengan batasan-batasan sebelumnya dari sistem itu.
Beberapa contoh dari apa yang saya temui yang tidak sesuai dengan model relasional:
code1,code2, ..., code20
)Alasan saya diberikan untuk keputusan desain itu semua didasarkan pada kendala sistem ketika database pertama kali dirancang.
Tanggal - saya diberitahu bahwa butuh lebih banyak waktu pemrosesan untuk menggunakan fungsi tanggal (yang bulan atau hari atau hari kerja) untuk memproses tanggal daripada yang dibuat untuk membuat tabel setiap tanggal yang mungkin dengan semua informasi itu.
Kolom berurutan dengan jenis yang sama - Lingkungan pemrogramannya memungkinkan program membuat variabel array di atas bagian baris. Dan itu adalah cara yang lebih mudah untuk mengurangi jumlah operasi baca.
NxM Panjang CHAR kolom - Lebih mudah untuk mendorong nilai konfigurasi menjadi satu kolom untuk mengurangi operasi membaca file.
Contoh kurang dipahami dalam C setara dengan mencerminkan lingkungan pemrograman yang mereka miliki:
Menurut apa yang saya katakan, beberapa di antaranya dianggap praktik terbaik pada saat itu.
sumber