tabel pesanan eCommerce. Simpan harga, atau gunakan tabel audit / riwayat?

13

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_itemdan aproduct

A productdapat dibeli. Ini memiliki berbagai detail, tetapi yang paling penting adalah unit_price.

Sebuah order_line_itemmemiliki kunci asing untuk product_idpembelian, quantitypembelian dan unit_pricepada saat pelanggan membeli produk.

Sebagian besar dari apa yang saya baca mengatakan bahwa unit_pricepada order_line_itemharus 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_pricenilai ke order_line_item?

Bukankah lebih baik membuat tabel audit / sejarah yang mendokumentasikan unit_priceperubahan product?

Ketika suatu order_line_itemdibuat, kunci asing dari product_audittabel 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.

Gaz_Edge
sumber
Saya sebenarnya akan melakukan keduanya: menyimpan harga penjualan di order_line dan menyimpan sejarah harga produk. Karena keduanya melayani tujuan yang berbeda. Menyimpan harga penjualan akan membuat kueri pesanan lebih mudah dan lebih cepat. Di sisi lain Anda mungkin ingin mengambil harga lama bahkan untuk produk yang belum terjual.
a_horse_with_no_name
Tentunya membuat permintaan pesanan lebih mudah tidak bisa menjadi satu-satunya penggerak di belakang penghematan harga akhir setiap saat. Ini adalah database relasional setelah semua - pertanyaan tidak akan jauh lebih sulit.
Gaz_Edge
3
Menyimpan harga penjualan di baris pesanan bukan "non-relasional" (dan saya menganggapnya normal serta harga penjualan adalah atribut langsung dari garis pesanan menurut saya). Seni menggunakan database relasional adalah tentang mengetahui batas-batasnya. Jika Anda menjalankan toko dengan 100 produk dan 5 pesanan sehari, maka menyimpan dan mengambil harga lama bukanlah masalah. Jika Anda menjalankan pasar dengan jutaan produk, ribuan dealer, dan jumlah pemesanan per menit, maka menanyakan sejarah itu akan menjadi masalah.
a_horse_with_no_name
Di mana Anda menyimpan harga histori? Dari apa yang saya baca saya butuh dua database. Satu untuk OLTP satu untuk OLAP. Sejarah berjalan di OLAP?
Gaz_Edge

Jawaban:

10

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:

  • Melalui telepon
  • Agen penjualan "di jalan"
  • Di lokasi fisik (mis. Toko, kantor)

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!

Chris Saxon
sumber
3

Saya akan menambahkan beberapa poin praktis yang telah saya lihat.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

mu 無
sumber
2

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!

oucil
sumber
itu tidak masuk akal untuk mengatakan bahwa Anda tidak menggunakannya karena itu bisa dihapus. Anda dapat mengganti data apa pun. Strategi apa pun harus menyimpan cadangan
Gaz_Edge
@Gaz_Edge Mereka tidak saling eksklusif, Anda masih dapat menggunakan jejak audit, dan menyimpan detail dengan transaksi, redundansi dalam kasus ini dibenarkan. Jangan pernah meninggalkan diri Anda dengan data subjek penting ini ke satu titik kegagalan. Dalam kasus kami, saya menggunakan toko objek terpusat sebagai mekanisme riwayat daripada mencoba membangun sejarah per jenis objek (seperti transaksi atau produk dalam kasus ini). Saya akan memiliki seluruh objek transaksi dalam sejarah tetapi semua detail terpenting dengan catatan itu sendiri. Itu sepenuhnya mengesampingkan objek produk dalam sejarah.
oucil
dan bagaimana jika saya ingin menjalankan laporan pesanan? Seperti berapa banyak produk x yang telah dibeli? Atau berapa banyak pesanan yang melebihi jumlah Anda? Menyimpan sebagai XML berarti Anda kehilangan kemampuan untuk meminta data, kecuali saya salah
Gaz_Edge
@Gaz_Edge Tidak benar, jika Anda berbicara MySQL, Anda 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 mengatur elasticsearchserver / instance yang memiliki pelaporan gaya BigData dan mudah menskala ke jutaan dokumen.
oucil
@Gaz_Edge Saya juga harus menyebutkan, laporan yang Anda bicarakan (pembelian lebih dari nilai, penjualan produk, dll.) Adalah laporan umum dan harus memiliki nilai yang disimpan sebagai nilai kolom dengan catatan transaksi untuk pemrosesan lebih cepat. Apa pun yang penting tetapi tidak harus dilaporkan sering dapat masuk ke XML. Data snapshot benar-benar hanya untuk dua hal, 1. masalah Dimensi yang Berubah Secara perlahan, dan 2. Validasi dan perbandingan saat pelanggan mengeluh, dan Anda harus segera melihat siapa yang benar. Ini tidak untuk digunakan setiap hari.
oucil
1

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.

njkroes
sumber
Terima kasih atas jawabannya. Saya pikir strategi yang saya gunakan adalah mendesain OLTP per buku. Saya benar-benar menyukai gagasan memiliki data warehouse untuk pelaporan. Meskipun menambahkan beberapa pekerjaan tambahan (membuat skema baru) skema tersebut dapat disesuaikan dengan OLAP. Semacam menghindari skenario di mana saya mencoba memasukkan pasak persegi dalam lubang bundar.
Gaz_Edge
@Gaz_Edge: Saya dalam situasi yang sama dalam hal membuat keputusan untuk proyek baru saya. Bisakah Anda peduli untuk membagikan pemikiran Anda tentang pendekatan desain apa yang Anda ambil setahun yang lalu? Apakah itu bekerja dengan baik?
Coder Absolute
@CoderAbsolute solusi asli saya sangat berorientasi 'database'. Aplikasi saya sekarang berpusat di sekitar Arsitektur Berorientasi Layanan. Saya sekarang memiliki banyak skema basis data kecil yang terpisah daripada satu yang sangat erat. Kebutuhan untuk 3N di satu skema besar sekarang telah hilang. Jadi saya sekarang hanya menambahkan harga satuan langsung ke pesanan. Menjaga perubahan harga produk bersejarah kini telah lenyap karena itu bukan persyaratan bisnis. Semoga itu bisa membantu.
Gaz_Edge
0

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.

Waku-2
sumber
Beberapa contoh kecil akan membuat jawaban Anda lebih mudah dimengerti. Terutama kalimat seperti 'pesanan adalah cuplikan yang diambil dari peristiwa yang sangat istimewa dalam siklus aplikasi Anda'.
dezso