Latar Belakang
Saya seorang siswa CS tahun pertama dan saya bekerja paruh waktu untuk bisnis kecil ayah saya. Saya tidak punya pengalaman dalam pengembangan aplikasi dunia nyata. Saya telah menulis skrip dengan Python, beberapa kursus di C, tapi tidak seperti ini.
Ayah saya memiliki bisnis pelatihan kecil dan saat ini semua kelas dijadwalkan, direkam, dan ditindaklanjuti melalui aplikasi web eksternal. Ada fitur ekspor / "laporan" tetapi sangat umum dan kami membutuhkan laporan spesifik. Kami tidak memiliki akses ke database aktual untuk menjalankan kueri. Saya diminta membuat sistem pelaporan khusus.
Ide saya adalah untuk membuat ekspor CSV generik dan mengimpor (mungkin dengan Python) mereka ke dalam database MySQL yang dihosting di kantor setiap malam, dari mana saya dapat menjalankan permintaan spesifik yang diperlukan. Saya tidak memiliki pengalaman dalam database tetapi memahami dasar-dasarnya. Saya sudah membaca sedikit tentang pembuatan basis data dan formulir normal.
Kami mungkin akan segera memiliki klien internasional, jadi saya ingin database tidak meledak jika / ketika itu terjadi. Kami juga saat ini memiliki beberapa perusahaan besar sebagai klien, dengan divisi yang berbeda (misalnya perusahaan induk ACME, divisi perawatan ACME, divisi perawatan tubuh ACME)
Skema yang saya buat adalah sebagai berikut:
- Dari perspektif klien:
- Klien adalah tabel utama
- Klien terhubung dengan departemen tempat mereka bekerja
- Departemen dapat tersebar di seluruh negara: SDM di London, Pemasaran di Swansea, dll.
- Departemen terkait dengan divisi perusahaan
- Divisi terkait dengan perusahaan induk
- Dari perspektif kelas:
- Sesi adalah tabel utama
- Seorang guru terhubung dengan setiap sesi
- Statusid diberikan untuk setiap sesi. Misalnya 0 - Selesai, 1 - Dibatalkan
- Sesi dikelompokkan menjadi "paket" dengan ukuran sewenang-wenang
- Setiap paket ditugaskan ke klien
- Sesi adalah tabel utama
Saya "mendesain" (lebih seperti mencoret-coret) skema pada selembar kertas, mencoba membuatnya tetap dinormalisasi ke bentuk ke-3. Saya kemudian menancapkannya ke MySQL Workbench dan itu membuat semuanya cantik untuk saya:
( Klik di sini untuk grafik berukuran penuh )
(sumber: maian.org )
Contoh kueri yang akan saya jalankan
- Klien dengan kredit yang masih tersisa tidak aktif (mereka yang tidak memiliki kelas dijadwalkan di masa mendatang)
- Berapa tingkat kehadiran per klien / departemen / divisi (diukur dengan status id di setiap sesi)
- Berapa banyak kelas yang dimiliki seorang guru dalam sebulan
- Tandai klien yang memiliki tingkat kehadiran rendah
- Laporan khusus untuk departemen SDM dengan tingkat kehadiran orang di divisi mereka
Pertanyaan
- Apakah ini overengineered atau saya menuju ke arah yang benar?
- Apakah kebutuhan untuk bergabung dengan beberapa tabel untuk sebagian besar kueri menghasilkan hit kinerja besar?
- Saya telah menambahkan kolom 'lastsession' ke klien, karena itu mungkin akan menjadi permintaan umum. Apakah ini ide yang bagus atau haruskah saya menjaga database tetap normal?
Terima kasih atas waktunya
sumber
divisions
memiliki kolom bernamadivisionid
. Apakah Anda tidak menemukan itu berlebihan? Sebut sajaid
. juga nama tabel Anda termasuk_has_
: saya akan menghapusnya dan beri nama saja misalnyacities_departments
.DATETIME
kolom Anda harus bertipeTIMESTAMP
kecuali nilai input pengguna. Saya pikir itu ide yang baik untuk memilikicities
dancountries
tabel. Anda mungkin mengalami kesulitan membatasi tabel ke satustatus
. pertimbangkan untuk menggunakanINT
dan melakukan perbandingan bitwise di atasnya- sehingga Anda dapat memiliki lebih banyak makna di sanaJawaban:
Beberapa jawaban lagi untuk pertanyaan Anda:
1) Kamu cukup tepat sasaran untuk seseorang yang mendekati masalah seperti ini untuk pertama kalinya. Saya pikir petunjuk dari orang lain tentang pertanyaan ini sejauh ini cukup banyak membahasnya. Kerja bagus!
2 & 3) Performa hit yang akan Anda ambil akan sangat tergantung pada memiliki dan mengoptimalkan indeks yang tepat untuk pertanyaan / prosedur khusus Anda dan yang lebih penting adalah volume rekaman. Kecuali jika Anda berbicara tentang lebih dari satu juta catatan di tabel utama Anda, Anda tampaknya berada di jalur untuk memiliki desain arus utama yang memadai bahwa kinerja tidak akan menjadi masalah pada perangkat keras yang masuk akal.
Yang mengatakan, dan ini berkaitan dengan pertanyaan Anda 3, dengan permulaan yang Anda miliki Anda mungkin tidak harus terlalu khawatir tentang kinerja atau hiper-sensitivitas terhadap normalisasi ortodoksi di sini. Ini adalah server pelaporan yang Anda bangun, bukan aplikasi backend berbasis transaksi, yang akan memiliki profil yang jauh berbeda sehubungan dengan pentingnya kinerja atau normalisasi. Basis data yang mendukung aplikasi pendaftaran dan penjadwalan langsung harus memperhatikan pertanyaan yang membutuhkan waktu beberapa detik untuk mengembalikan data. Tidak hanya fungsi server laporan yang lebih toleran terhadap kueri yang rumit dan panjang, tetapi strategi untuk meningkatkan kinerja jauh berbeda.
Misalnya, dalam lingkungan aplikasi berbasis transaksi, opsi peningkatan kinerja Anda mungkin termasuk refactoring prosedur tersimpan Anda dan struktur tabel ke tingkat n, atau mengembangkan strategi caching untuk sejumlah kecil data yang biasanya diminta. Dalam lingkungan pelaporan Anda tentu dapat melakukan ini tetapi Anda dapat memiliki dampak yang lebih besar pada kinerja dengan memperkenalkan mekanisme snapshot di mana proses yang dijadwalkan berjalan dan menyimpan laporan yang telah dikonfigurasi sebelumnya dan pengguna Anda mengakses data snapshot tanpa tekanan pada tingkat db Anda pada per permintaan dasar.
Semua ini adalah kata-kata kasar yang bertele-tele untuk menggambarkan bahwa prinsip-prinsip dan trik desain apa yang Anda gunakan mungkin berbeda mengingat peran db yang Anda buat. Saya harap itu membantu.
sumber
Anda punya ide yang tepat. Namun Anda dapat membersihkannya, dan menghapus beberapa tabel pemetaan (memiliki *).
Apa yang dapat Anda lakukan adalah di tabel Departemen, tambahkan CityId dan DivisionId.
Selain itu, saya pikir semuanya baik-baik saja ...
sumber
Satu-satunya perubahan yang akan saya lakukan adalah:
1- Ubah VARCHAR Anda menjadi NVARCHAR, jika Anda ingin go internasional, Anda mungkin ingin unicode.
2- Ubah id int Anda menjadi GUIDs (uniqueidentifier) jika memungkinkan (ini mungkin hanya preferensi pribadi saya). Dengan asumsi Anda akhirnya sampai pada titik di mana Anda memiliki beberapa lingkungan (dev / test / staging / prod), Anda mungkin ingin memigrasikan data dari satu ke yang lain. Memiliki GUID Id membuat ini secara signifikan lebih mudah.
3- Tiga lapisan untuk Perusahaan Anda -> Divisi -> Struktur departemen mungkin tidak cukup. Sekarang, ini mungkin rekayasa berlebihan, tetapi Anda bisa menggeneralisasi hierarki sedemikian rupa sehingga Anda dapat mendukung n-level kedalaman. Ini akan membuat beberapa pertanyaan Anda lebih kompleks, sehingga mungkin tidak sepadan dengan trade-off. Lebih lanjut, bisa jadi bahwa setiap klien yang memiliki lebih banyak lapisan dapat dengan mudah "dimasukkan" ke dalam model ini.
4- Anda juga memiliki Status di Tabel Klien yang merupakan VARCHAR dan tidak memiliki tautan ke tabel Statuses. Saya berharap ada sedikit kejelasan tentang apa yang diwakili Status Klien.
sumber
Tidak. Sepertinya Anda mendesain pada tingkat detail yang baik.
Saya pikir Negara dan Perusahaan benar-benar entitas yang sama dalam desain Anda, seperti Kota dan Divisi. Saya akan menyingkirkan tabel Negara dan Kota (dan Kota_Has_Departemen) dan, jika perlu, tambahkan boolean flag IsPublicSector ke tabel Companies (atau kolom CompanyType jika ada lebih banyak pilihan daripada sekadar Sektor Swasta / Sektor Publik).
Juga, saya pikir ada kesalahan dalam penggunaan tabel Departemen Anda. Sepertinya tabel Departemen berfungsi sebagai referensi ke berbagai jenis departemen yang masing-masing divisi pelanggan dapat miliki. Jika demikian, itu harus disebut DepartmentTypes. Tetapi klien Anda (yang saya anggap sebagai peserta) bukan milik TYPE departemen, mereka milik instance departemen aktual di perusahaan. Seperti yang ada sekarang, Anda akan tahu bahwa klien yang diberikan milik departemen SDM di suatu tempat, tetapi bukan yang mana!
Dengan kata lain, Klien harus ditautkan ke tabel yang Anda panggil Divisions_Has_Departments (tapi yang saya sebut hanya Departemen). Jika demikian, maka Anda harus merobohkan Kota ke Divisi seperti yang dibahas di atas jika Anda ingin menggunakan integritas referensial standar dalam database.
sumber
Omong-omong, perlu dicatat bahwa jika Anda sudah menghasilkan CSV dan ingin memuatnya ke dalam database mySQL, LOAD DATA LOCAL INFILE adalah teman terbaik Anda: http://dev.mysql.com/doc/refman/5.1/ id / muat-data.html . Mysqlimport juga layak untuk dilihat, dan merupakan alat baris perintah yang pada dasarnya pembungkus yang bagus untuk memuat data infile.
sumber
Sebagian besar hal telah dikatakan, tetapi saya merasa bahwa saya dapat menambahkan satu hal: cukup umum bagi pengembang yang lebih muda untuk khawatir tentang kinerja sedikit terlalu banyak di muka, dan pertanyaan Anda tentang bergabung dengan tabel tampaknya mengarah ke arah itu. Ini adalah anti-pola pengembangan perangkat lunak yang disebut ' Premature Optimization '. Cobalah untuk mengusir refleks itu dari pikiran Anda :)
Satu hal lagi: Apakah Anda percaya Anda benar-benar membutuhkan tabel 'kota' dan 'negara'? Tidakkah memiliki kolom 'kota' dan 'negara' di tabel departemen cukup untuk kasus penggunaan Anda? Misalnya apakah aplikasi Anda perlu membuat daftar departemen menurut kota dan kota demi negara?
sumber
Berikut komentar berdasarkan peran sebagai spesialis Intelijen / Pelaporan Bisnis dan manajer strategi / perencanaan:
Saya setuju dengan arahan Larry di atas. IMHO, Ini tidak terlalu banyak direkayasa, beberapa hal hanya terlihat sedikit tidak pada tempatnya. Untuk membuatnya tetap sederhana, saya akan menandai klien langsung ke ID Perusahaan, Deskripsi Departemen, Deskripsi Divisi, ID Jenis Departemen, ID Jenis Divisi. Gunakan ID Jenis Departemen dan ID Jenis Divisi sebagai referensi untuk tabel pencarian dan bidang pelaporan / analisis internal untuk konsistensi jangka panjang.
Tabel paket berisi kolom "Kredit", bukankah seharusnya itu benar-benar diikat ke tabel basis Klien sehingga jika mereka banyak paket, Anda dapat melihat berapa banyak utang kredit yang tersisa untuk kelas mendatang? Aplikasi dapat menangani calc dan menyimpannya secara terpusat di tabel Klien.
Info perusahaan dapat menggunakan lebih banyak bidang, termasuk alamat yang jelas / telepon / dll. informasi. Saya juga akan siap untuk menambahkan kolom D & B "DUN" (Situs / Cabang / Ultimate) jangka panjang, Dun dan Bradstreet (D & B) memiliki katalog besar perusahaan dan Anda akan menemukan kemudian jalan informasi mereka sangat membantu untuk pelaporan / analisis. Ini akan menangani masalah beberapa divisi yang Anda sebutkan, dan memungkinkan Anda untuk menggulung hierarki mereka untuk sub / divisi / cabang / dll. korps besar.
Anda tidak menyebutkan berapa banyak catatan yang akan Anda kerjakan yang bisa menyiratkan pengaturan diri Anda untuk inisiatif pengembangan besar yang bisa dilakukan lebih cepat dan jauh lebih sedikit sakit kepala dengan perangkat lunak "pelaporan" yang telah dikemas. Jika Anda tidak berurusan dengan database yang besar (<65000) baris, pastikan MS-Access, OpenOffice (Base) atau solusi laporan / pengembang aplikasi terkait tidak bisa melakukan trik. Saya menggunakan perangkat lunak APEX Oracle gratis sedikit sendiri, ia datang dengan database gratis mereka Oracle XE hanya mengunduhnya dari situs mereka.
FYI - Wawasan pelaporan: untuk basis data besar, Anda biasanya memiliki dua contoh basis data a) basis data transaksi untuk merekam setiap catatan terperinci. b) pelaporan basis data (data mart / data warehouse) yang ditempatkan pada mesin terpisah. Untuk informasi lebih lanjut cari google Skema Bintang dan Skema Snowflake.
Salam.
sumber
Saya ingin membahas hanya kekhawatiran bahwa bergabung dengan tabel mutiple akan menyebabkan hit kinerja. Jangan takut untuk menjadi normal karena Anda harus bergabung. Bergabung adalah normal dan diharapkan dalam basis data relasional dan mereka dirancang untuk menanganinya dengan baik. Anda perlu mengatur hubungan PK / FK (untuk integritas data, ini penting untuk dipertimbangkan dalam mendesain) tetapi dalam banyak basis data, FK tidak secara otomatis diindeks. Karena mereka akan digunakan dalam bergabung, Anda akan ingin mendaftar dengan mulai mengindeks FKS. PK umumnya mendapatkan indeks pada penciptaan karena mereka harus unik. Memang benar bahwa desain datawarehouse mengurangi jumlah gabungan, tetapi biasanya seseorang tidak sampai ke pergudangan data sampai seseorang memiliki jutaan catatan yang perlu diakses dalam satu laporan. Bahkan hampir semua gudang data mulai dengan database transaksional untuk mengumpulkan data secara real time dan kemudian data dipindahkan ke gudang sesuai jadwal (malam atau bulanan atau apa pun kebutuhan bisnis). Jadi ini adalah awal yang baik bahkan jika Anda perlu merancang data warehouse nanti untuk meningkatkan kinerja laporan.
Saya harus mengatakan desain Anda sangat mengesankan untuk siswa CS tahun pertama.
sumber
Ini bukan rekayasa berlebihan, ini adalah bagaimana saya akan mendekati masalah. Bergabung dengan baik-baik saja, tidak akan ada banyak hit kinerja (itu benar-benar diperlukan kecuali Anda mende-normalisasi database yang tidak direkomendasikan!). Untuk status, lihat apakah Anda dapat menggunakan enum datatype sebagai gantinya untuk mengoptimalkan tabel itu.
sumber
Saya telah bekerja di domain pelatihan / sekolah dan saya pikir saya akan menunjukkan bahwa pada umumnya ada hubungan M: 1 antara apa yang Anda sebut "sesi" (contoh dari kursus yang diberikan) dan kursus itu sendiri. Dengan kata lain, katalog Anda menawarkan kursus ("Spanyol 101" atau apa pun), tetapi Anda mungkin memiliki dua contoh yang berbeda selama satu semester (Tu-Th diajarkan oleh Smith, Wed-Fri diajar oleh Jones).
Selain itu, sepertinya ini awal yang baik. Saya yakin Anda akan menemukan bahwa domain klien (grafik yang mengarah ke "klien") lebih kompleks daripada yang Anda modelkan, tetapi jangan berlebihan dengan hal itu sampai Anda memiliki beberapa data nyata untuk memandu Anda.
sumber
Beberapa hal muncul dalam pikiran:
Tabel-tabel itu tampaknya cocok untuk pelaporan, tetapi tidak benar-benar menjalankan bisnis. Saya akan berpikir ketika klien mendaftar, pada dasarnya ada pesanan yang ditempatkan untuk klien menghadiri daftar sesi, dan pesanan itu mungkin untuk beberapa karyawan di satu perusahaan. Tampaknya tabel "pesanan" akan benar-benar berada di pusat sistem Anda dan mendorong pengambilan data dan pelaporan akhirnya. (Bandingkan dokumen kertas yang telah Anda gunakan untuk menjalankan bisnis dengan desain database Anda untuk melihat apakah ada kecocokan logis.)
Perusahaan seringkali tidak memiliki divisi. Karyawan terkadang mengubah divisi / departemen, bahkan mungkin pertengahan sesi. Perusahaan terkadang menambah / menghapus / mengganti nama divisi / departemen. Pastikan kemungkinan perubahan konten waktu nyata dari tabel Anda tidak mempersulit pelaporan / pengelompokan berikutnya. Dengan begitu banyak data kontak yang terbagi atas begitu banyak tabel, Anda mungkin harus menerapkan validasi entri data yang sangat ketat untuk menjaga laporan Anda bermakna dan inklusif. Misalnya, ketika klien baru ditambahkan, pastikan perusahaan / divisi / departemen / kotanya cocok dengan nilai yang sama dengan rekan kerjanya.
Konsep "paket" tidak jelas sama sekali.
Karena Anda mengindikasikan itu adalah bisnis kecil, akan mengejutkan jika kinerja akan menjadi masalah, mengingat kecepatan dan kapasitas mesin saat ini.
sumber