Saya sedang merancang skema eCommerce pertama saya. Saya telah membaca sekitar subjek untuk sementara waktu, dan saya agak bingung tentang hubungan antara a order_line_item
dan aproduct
A product
dapat dibeli. Ini memiliki berbagai detail, tetapi yang paling penting adalah unit_price
.
Sebuah order_line_item
memiliki kunci asing untuk product_id
pembelian, quantity
pembelian dan unit_price
pada saat pelanggan membeli produk.
Sebagian besar dari apa yang saya baca mengatakan bahwa unit_price
pada order_line_item
harus ditambahkan secara eksplisit (yaitu tidak dirujuk melalui product_id
). Masuk akal, karena toko dapat mengubah harga di masa depan yang akan mengacaukan laporan pesanan, pelacakan, integritas dll.
Hal yang saya tidak mengerti, mengapa langsung menyimpan unit_price
nilai ke order_line_item
?
Bukankah lebih baik membuat tabel audit / sejarah yang mendokumentasikan unit_price
perubahan product
?
Ketika suatu order_line_item
dibuat, kunci asing dari product_audit
tabel ditambahkan dan harga dapat diambil (dengan referensi) dari sana.
Tampaknya bagi saya ada banyak hal positif untuk menggunakan pendekatan ini (lebih sedikit duplikasi data, riwayat perubahan harga, dll), jadi mengapa tidak lebih sering digunakan? Saya belum menemukan contoh skema eCommerce yang menggunakan pendekatan ini, apakah saya kehilangan sesuatu?
UDPATE: Sepertinya pertanyaan saya terkait dengan Perlahan Mengubah Dimensi . Saya masih bingung karena Dimensi Perlahan-lahan Berubah berkaitan dengan data warehouse dan OLAP. Jadi bisakah jenis Slowy Changing Dimension diterapkan ke basis data proses transaksi bisnis utama (OLTP) saya? Saya bertanya-tanya apakah saya sedang mencampur banyak konsep, Akan sangat menghargai panduan.
sumber
Jawaban:
Seperti yang telah Anda identifikasi, menyimpan harga pada pesanan membuat implementasi teknis lebih mudah. Ada beberapa alasan bisnis mengapa ini dapat bermanfaat.
Selain transaksi web, banyak bisnis mendukung penjualan melalui saluran lain, misalnya:
Dalam kasus ini pesanan dapat dimasukkan ke dalam sistem beberapa saat setelah transaksi terjadi. Dalam keadaan ini mungkin sulit untuk tidak mungkin mengidentifikasi dengan benar catatan harga historis mana yang harus digunakan - menyimpan harga satuan secara langsung pada pesanan adalah satu-satunya pilihan yang layak.
Banyak saluran seringkali membawa tantangan lain - harga berbeda untuk produk yang sama. Biaya tambahan untuk pesanan telepon adalah umum - dan beberapa pelanggan mungkin menegosiasikan diri mereka dengan diskon. Anda mungkin dapat mewakili semua harga yang mungkin untuk semua saluran dalam skema produk Anda, tetapi memasukkan ini ke dalam tabel pesanan Anda dapat menjadi (sangat) kompleks.
Di mana pun negosiasi diizinkan, akan sangat sulit untuk menautkan riwayat harga ke harga pesanan yang disepakati (kecuali jika agen memiliki batas negosiasi yang sangat sempit). Anda perlu menyimpan harga pada pesanan itu sendiri.
Bahkan jika Anda hanya mendukung transaksi web dan memiliki struktur harga yang relatif sederhana, masih ada masalah yang menarik untuk diatasi - bagaimana seharusnya kenaikan harga ditangani dalam transaksi penerbangan? Apakah bisnis bersikeras bahwa pelanggan harus membayar kenaikan atau apakah mereka menghormati harga asli (ketika produk ditambahkan ke keranjang)? Jika itu yang terakhir itu implementasi teknisnya rumit - Anda perlu menemukan cara untuk memastikan Anda mempertahankan versi harga di sesi dengan benar.
Akhirnya, banyak bisnis mulai menggunakan harga yang sangat dinamis. Mungkin tidak ada satu harga tetap untuk suatu produk - itu selalu dihitung pada saat runtime berdasarkan faktor-faktor seperti waktu hari, permintaan untuk produk dan sebagainya. Dalam kasus ini, harga mungkin tidak disimpan terhadap produk sejak awal!
sumber
Saya akan menambahkan beberapa poin praktis yang telah saya lihat.
Produk bersifat sementara.
Apa yang mereka tandakan hari ini, mungkin tidak sama dengan apa yang mereka tandai setahun yang lalu. Kode sku yang sama (dan karenanya product_id), mungkin merujuk ke berbagai varian / jenis produk pada tahapan yang berbeda.
Tidak semua orang memahami semua masalah yang ada; karenanya pengguna dapat mengubah atrribut produk asli alih-alih membuat yang baru dari ketidaktahuannya sendiri. Banyak kali, ini bisa terjadi karena rencana pengguna aktif (Hei! Saya dapat memiliki 100 sku saja, jadi mengapa tidak terus mengubah yang lebih lama daripada memperbarui rencana) Jadi, Anda lihat, di banyak kereta , suatu produk tidak akan pernah menandakan hal yang sama selamanya.
Harga berbeda berdasarkan kondisi pemesanan dan pengiriman
Seperti yang disebutkan pengguna @Chris, harga yang berbeda mungkin berlaku dalam skenario yang berbeda.
Di sebagian besar gerobak, Anda akan menemukan setidaknya 3 bidang yang berbeda disimpan - harga satuan, jumlah diskon dan harga diskon. Di yang lebih maju, Anda akan menemukan 2 lebih - harga satuan dengan pajak, harga diskon dengan pajak. Anda mungkin menemukan beberapa bidang lagi untuk menjelaskan biaya metode pengiriman, dan biaya metode pembayaran tambahan. Persen pajak dapat bervariasi tergantung pada negara, produk, negara, metode pengiriman, dan sebagainya, dan begitu pula kepala biaya lainnya. Demikian pula diskon dapat bervariasi tergantung pada geografi, promosi, waktu penjualan dan sebagainya. Oleh karena itu, ada informasi yang dapat diperoleh pada tingkat pesanan saja, dan informasi gabungan ini tidak dapat dihasilkan dari data dalam tabel produk saja.
Pemisahan masalah
Banyak kereta diterapkan dengan cara, sehingga tim yang berbeda dapat memiliki kontrol atas bagian data yang berbeda. Seseorang yang mengelola sistem pesanan tidak selalu perlu tahu apa semua stok produk, berapa harga di titik waktu yang berbeda, apa alternatif untuk sku tertentu, dan sebagainya. Menyimpan data terkait produk bersama dengan data pesanan membantu mencapai pemisahan yang menjadi perhatian. Ini juga bisa benar pada tahap pengembangan, jika tim yang berbeda mengelola bagian sistem yang berbeda.
Skalabilitas yang lebih mudah di berbagai sistem
Sering kali, Sistem Manajemen Pesanan, Mesin Aturan, Mesin Katalog, Sistem Manajemen Konten semuanya dibangun / dikelola sebagai sistem yang terpisah. Ini membantu mengoptimalkan berbagai kondisi beban dan menghasilkan kecerdasan khusus untuk masing-masing sistem. Satu sistem, maka, tidak dapat ditahan untuk tebusan karena tidak tersedianya informasi dari sistem lain.
Pengembangan lebih cepat dan waktu berjalan
Saya telah menggunakan istilah "waktu pengembangan" di sini, meskipun menggunakan "waktu debug" akan lebih tepat. Setiap kali perkembangan baru terjadi, akan lebih cepat jika data yang dibutuhkan tersedia tanpa menambah kompleksitasnya sendiri, karena dengan demikian, akan ada siklus debugging yang relatif lebih kecil.
Bayangkan Anda diminta untuk membuat laporan berdasarkan permintaan untuk diskon yang ditawarkan setiap hari selama sebulan setengah tahun yang lalu. Jika Anda memiliki harga asli, harga diskon dalam 1-2 tabel beserta pesanan, detail barang pesanan, ini cukup mudah. Namun, jika Anda harus pergi dan mengambil harga dari tabel lain, dan kemudian diskon yang berlaku dari tabel lain, dan kemudian mencari tahu detailnya, baik waktu pengembangan dan waktu berjalan akan lebih tinggi.
Desain yang baik harus berusaha mengoptimalkan sebanyak mungkin untuk masa depan, sebagaimana seharusnya untuk saat ini.
sumber
Mungkin berakhir dengan biaya penyimpanan yang lebih besar, tetapi saya lebih suka menyimpan semua detail penjualan yang relevan dengan transaksi itu sendiri, sehingga jika karena alasan apa pun jejak audit kami rusak, atau administrator menimpa keamanan di tempat, rincian dari penjualan seperti: mata uang yang digunakan, harga satuan, jumlah, pajak yang diterapkan dan berapa nilai mereka, dll. semuanya tersedia. Saya biasanya menyimpannya sebagai XML sehingga bisa fleksibel dari penjualan ke penjualan.
EDIT: Untuk memperluas apa yang saya katakan secara singkat di atas, dalam komentar tindak lanjut saya di bawah, dan apa yang disentuh @a_horse_with_no_name di atas, redundansi dalam data transaksi tidak hanya penting, tetapi juga perlu pada skala.
Saya berasumsi bahwa Anda membangun menggunakan OOP dan karenanya Anda harus memiliki objek transaksi dan objek produk yang mencakup semuanya dan / atau objek harga. Dalam pengalaman pribadi saya, saya lebih suka menjadi verbal dalam sejarah saya, penyimpanan relatif ciak.
Apa yang telah kami lakukan adalah membuat riwayat objek yang dapat Anda fasilitasi menggunakan RDBMS Anda yang sudah ada atau semacam penyimpanan nilai kunci NOSQL (atau bahkan lebih baik RDBMS yang memungkinkan koneksi seperti NoSQL seperti handlersocket atau memcache), dan kami menyimpan riwayat objek dengan begitu, dengan setiap detail dan perubahan harga di satu tempat tersedia dengan mudah dan cepat. Jika Anda serius, Anda bahkan bisa menggunakan DIFF untuk menghemat penyimpanan dan hanya menyimpan perubahan ke depan, meskipun memiliki peringatan sendiri. Yang seharusnya menjaga sejarah Anda, dan keuntungan dari objek bersambung adalah bahwa sistem Anda akan / harus dapat mengembalikannya sebagai objek yang disimpan. Itu menangani sejarah.
Berkenaan dengan saran saya, menyimpan detail transaksi seperti pajak, mata uang, dll. Dengan transaksi itu sendiri berarti tidak perlu mencari di tempat lain untuk rincian tersebut, objek transaksi Anda akan mengetahui propertinya dan Anda dilihat dapat mengurus penyajiannya. data yang bervariasi sesuai keinginan Anda. Anda mendapatkan akses cepat ke foto dan memiliki manfaat tambahan dari catatan yang berlebihan dan dapat diverifikasi.
Ini layak, percayalah!
sumber
SELECT ExtractValue(field_name, '/x/path/');
dapat memfilter untuk hal-hal seperti, semua transaksi dalam mata uang tertentu, atau semua transaksi dengan nilai pajak minimum tertentu, atau apa pun. Laporan skala yang lebih besar dapat dilakukan dari sejarah objek. Untuk laporan skala yang lebih besar, Anda dapat mengaturelasticsearch
server / instance yang memiliki pelaporan gaya BigData dan mudah menskala ke jutaan dokumen.Pilihan saya adalah untuk menyimpan harga satuan pada item baris Anda dan melacak riwayat harga produk Anda di tabel terpisah. Pembenaran saya untuk ini adalah untuk menambah fleksibilitas.
Sekalipun struktur penetapan harga Anda kaku dan terdefinisi dengan baik dan tidak memungkinkan variasi yang disebutkan oleh @Chris Saxon di atas, apakah Anda merasa nyaman bahwa itu akan selalu seperti itu? Bahkan jika Anda percaya diri, mengapa mengecat diri sendiri? Saya pikir itu akan menjadi ide yang baik untuk menyimpan ini pada detail item baris karena saya tidak bisa memikirkan alasan kuat untuk membuatnya terpisah.
Adapun untuk menyimpan riwayat harga Anda, ada nilai yang pasti dalam menyimpannya secara terpisah karena mungkin ada perubahan harga barang dan tidak ada yang membelinya. Itu pasti info yang berguna untuk mengetahui apakah perubahan harga tidak efektif. Seperti yang Anda sebutkan, ini adalah kasus penggunaan klasik dari Tipe 2 Perlahan Mengubah Dimensi dalam skenario gudang data. Biasanya setiap perubahan harga di tabel produk Anda akan ditangkap dan baris baru akan ditambahkan ke tabel dimensi dengan harga yang diperbarui dan cap waktu untuk menunjukkan kapan perubahan ini terjadi. Baris sebelumnya akan memperbarui tanggal akhir untuk menunjukkan bahwa ini bukan lagi harga efektif. Jadi salah satu pendekatan akan melacak jenis perubahan ini dalam data warehouse.
Namun, jika Anda tidak ingin mengkhawatirkan diri Anda dengan merancang skema gudang data dan proses ETL pada saat yang sama seperti mendesain database e-niaga OLTP Anda, maka riwayat ini dapat dipastikan tersimpan dalam database e-niaga kami. Ini bisa dilakukan seperti yang Anda gambarkan dengan membuat tabel product_audit terpisah yang menggantung dari tabel produk dan berisi tanggal mulai dan berakhir ketika versi produk itu berlaku. Itu juga bisa dilakukan di tabel produk itu sendiri dengan menambahkan tanggal mulai dan berakhir ke tabel untuk menunjukkan produk mana yang sedang aktif. Namun, tergantung pada jumlah produk dan jumlah atau perubahan harga yang dialami perusahaan Anda, ini bisa membuat tabel produk Anda jauh lebih besar dari yang dimaksudkan dan dapat menyebabkan masalah kinerja permintaan di kemudian hari.
Terakhir, memisahkan riwayat harga Anda dari harga unit aktual pada item baris pasti dapat memberikan beberapa peluang analitik lain untuk melihat kapan suatu produk dijual dengan harga yang di atas atau di bawah harga yang tercantum pada saat itu.
sumber
Saya setuju sepenuhnya dengan ide utama menjaga ketertiban informasi (konteks) bersama. Hanya catatan kecil bahwa situasi seperti itu akan muncul hanya ketika Anda merancang aplikasi Anda sangat banyak basis data dan semuanya berputar di sekitar db gemuk besar. Jika Anda mengalihkan sudut pandang Anda dengan melihat domain masalah dari sudut yang berbeda, Anda akan dengan jelas mengamati bahwa urutan adalah potret yang diambil dari peristiwa yang sangat istimewa dalam siklus hidup aplikasi Anda. Ketika Anda menangani masalah berdasarkan konteks, maka masalah basis data akan menjadi masalah sekunder dan kerumitan yang membuat semua orang takut akan pertanyaan dan membuat laporan akan ditangani secara mulus dalam model domain.
sumber