e-Ticaret siparişleri tablosu. Fiyatları kaydet veya bir denetim / geçmiş tablosu mu kullanıyorsun?


13

İlk e-ticaret şememi tasarlıyorum. Bir süredir konuyu okuyorum order_line_itemve a ve a arasındaki ilişki hakkında biraz kafam karıştıproduct

A productsatın alınabilir. Çeşitli detaylara sahip, ama en önemlisi unit_price.

A order_line_item, product_idsatın alınan, quantitysatın alınan ve unit_pricemüşterinin ürünü satın aldığı zamanda yabancı bir anahtara sahiptir .

Ne okudum çoğu söylüyor unit_priceüzerinde order_line_itemaçıkça eklenmelidir (yani yoluyla başvuruda product_id). Mağazanın gelecekte sipariş raporlarını, izlemeyi, bütünlüğü vb. Bozacak fiyatı değiştirebileceği için mantıklı.

Anlamadığım şey, neden doğrudan kaydetme olduğu unit_priceiçin değer order_line_item?

A unit_pricedeğişikliğini belgeleyen bir denetim / geçmiş tablosu oluşturmak daha iyi olmaz mıydı product?

Bir order_line_itemoluşturulduğunda, product_audittablonun yabancı anahtarı eklenir ve fiyat oradan (referans olarak) alınabilir.

Bana bu yaklaşımı (veriyi daha az çoğaltmak, fiyat değişikliği geçmişi vb.) Kullanmanın birçok olumlu yanı var, neden daha sık kullanılmıyor? Bu yaklaşımı kullanan bir e-ticaret şeması örneği ile karşılaşmadım, bir şey mi kaçırıyorum?

UDPATE: Görünüşe göre sorum Yavaşça Değişen Boyut ile ilgili . Yavaşça Değişen Boyut, veri ambarı ve OLAP'larla ilgili olduğu için hala kafam karıştı. Yavaş Değişen Boyut türleri ana iş işlem süreci veritabanım (OLTP) için uygulanabilir mi? Bir sürü kavramı karıştırıp karıştırmayacağımı merak ediyorum, bazı rehberlikleri çok takdir ediyorum.


Aslında her ikisi de yapardı: order_line satış fiyatı depolamak ve ürün fiyatları geçmişini depolar. Çünkü her ikisi de farklı amaçlara hizmet ediyor. Satış fiyatının depolanması siparişlerle ilgili sorguları çok daha kolay ve hızlı hale getirecektir . Öte yandan, satılmayan ürünler için bile eski fiyatları almak isteyebilirsiniz.
a_horse_with_no_name

Kesinlikle sipariş sorgularını kolaylaştırmak, her seferinde nihai fiyatı kaydetmenin arkasındaki tek sürücü olamaz. Sonuçta bu ilişkisel bir veritabanı - o kadar zor olmazdı.
Gaz_Edge

3
Satış fiyatını sipariş satırında saklamak "ilişkisel olmayan" değildir (ve bence bu satış fiyatının yanı sıra satış fiyatlarının doğrudan bir özelliği olduğunu düşünüyorum). İlişkisel veritabanı kullanma sanatı sınırları bilmekle ilgilidir. Günde 100 ürün ve 5 sipariş içeren bir dükkan işletiyorsanız, eski fiyatları depolamak ve almak sorun değil. Dakikada milyonlarca ürün, binlerce bayi ve hundres sipariş ile bir pazar işletiyorsanız, bu geçmişi sorgulamak sorun olacaktır .
a_horse_with_no_name

Tarih fiyatlarını nerede depolarsınız? Okuduğum kadarıyla iki veritabanına ihtiyacım var. Biri OLTP için bir tane OLAP için. Tarih OLAP'a mı gidiyor?
Gaz_Edge

Yanıtlar:


10

Tanımladığınız gibi, fiyatı siparişte saklamak teknik uygulamayı kolaylaştırır. Bununla birlikte, bunun yararlı olabileceği birkaç iş nedeni vardır.

Web işlemlerine ek olarak, birçok işletme satışları diğer kanallar aracılığıyla destekler, örneğin:

  • Telefonda
  • Satış temsilcileri "yolda"
  • Fiziksel bir yerde (örneğin mağaza, ofis)

Bu durumlarda sipariş, işlemin gerçekleştirilmesinden bir süre sonra sisteme girilebilir. Bu durumlarda hangi tarihsel fiyat kaydının kullanılması gerektiğini doğru bir şekilde tanımlamak imkansız olabilir - birim fiyatı doğrudan sipariş üzerine saklamak tek uygun seçenektir.

Birden fazla kanal genellikle başka bir zorluk getirir - aynı ürün için farklı fiyatlar. Telefon siparişleri için ek ücretler yaygındır ve bazı müşteriler kendilerine indirim uygulayabilir. Ürün şemanızdaki tüm kanallar için olası tüm fiyatları temsil edebilirsiniz, ancak bunu sipariş tablolarınıza dahil etmek çok karmaşık olabilir.

Müzakereye izin verilen her yerde, fiyat geçmişini kararlaştırılan sipariş fiyatına bağlamak çok zorlaşır (acentelerin çok dar müzakere sınırları olmadığı sürece). Fiyatı siparişin kendisinde saklamanız gerekir.

Sadece web işlemlerini destekleseniz ve nispeten basit bir fiyatlandırma yapısına sahip olsanız bile, hala üstesinden gelmek için ilginç bir sorun var - uçuş işlemlerinde fiyat artışları nasıl ele alınmalı? İşletme, müşterinin artışları ödemesi gerektiğinde ısrar ediyor mu veya orijinal fiyatı (ürün sepete eklendiğinde) onurlandırıyor mu? İkincisi ise teknik uygulama karmaşıktır - oturumdaki fiyat sürümünü doğru bir şekilde koruduğunuzdan emin olmanın bir yolunu bulmanız gerekir.

Son olarak, birçok işletme son derece dinamik fiyatlandırmayı kullanmaya başladı. Belirli bir ürün için sabit bir fiyat olmayabilir - her zaman çalışma zamanında günün saati, ürün talebi vb. Faktörlere göre hesaplanır. Bu durumlarda, fiyat ilk etapta ürüne kaydedilemez!


3

Gördüğüm bazı pratik noktaları ekleyeceğim.

  1. Ürünler geçicidir.

    Bugün ne ifade edebilecekleri, bir yıl öncesini ifade ettikleri ile aynı olmayabilir. Aynı sku kodu (ve dolayısıyla product_id), farklı aşamalardaki ürünün farklı varyantına / türüne atıfta bulunabilir.

    Herkes elindeki tüm endişeleri anlamıyor; dolayısıyla kullanıcı kendi cehaletinden yeni bir ürün oluşturmak yerine orijinal ürünün özelliklerini değiştirebilir. Çoğu zaman, bu bir kullanıcının bulunduğu plan nedeniyle olabilir (Hey! Sadece 100 sku alabilirim, neden planı yükseltmek yerine eski olanları değiştirmeye devam etmiyorsun) Yani, görüyorsun, birçok arabada , bir ürün asla aynı şeyi sonsuza dek göstermeyecektir.

  2. Sipariş ve gönderim koşullarına göre farklı fiyatlar

    @Chris kullanıcısının belirttiği gibi, farklı senaryolarda farklı fiyatlar uygulanabilir.

    Çoğu arabada, depolanan en az 3 farklı alan bulacaksınız - birim fiyat, indirim tutarı ve indirimli fiyat. Daha gelişmiş olanlarda, vergi ile 2 birim daha, vergi ile indirimli fiyat bulacaksınız. Gönderim yöntemi ücretlerini ve ek ödeme yöntemi ücretlerini açıklamak için birkaç alan daha bulabilirsiniz. Vergi yüzdeleri devlete, ürüne, ülkeye, gönderim yöntemine vb. Bağlı olarak değişebilir ve diğer maliyet başlıkları da değişebilir. Benzer şekilde, indirimler coğrafyaya, promosyonlara, satış süresine vb. Göre değişebilir. Bu nedenle, yalnızca sipariş düzeyinde elde edilebilen bilgiler vardır ve bu birleşik bilgiler yalnızca ürünler tablosundaki verilerden üretilemez.

  3. Endişelerin ayrılması

    Bir sürü araba bir şekilde uygulanır, böylece farklı ekipler farklı veri bölümleri üzerinde kontrol sahibi olabilir. Sipariş sistemini yöneten bazılarının her zaman tüm ürünlerin stokta olduğunu, farklı zamanlarda fiyatlar neler olduğunu, belirli bir sku için alternatiflerin neler olduğunu bilmesine gerek yoktur. Ürünle ilgili verileri sipariş verileriyle birlikte tutmak, endişelerin ayrılmasını sağlar. Farklı ekipler sistemin farklı bölümlerini yönetiyorsa, bu geliştirme aşamalarında da geçerli olabilir.

  4. Birden çok sistemde daha kolay ölçeklenebilirlik

    Çoğu zaman, Sipariş Yönetim Sistemi, Kural Motoru, Katalog Motoru, İçerik Yönetim Sistemi kendi başına ayrı sistemler olarak inşa edilir / korunur. Bu, çeşitli yük koşulları için optimize edilmesine ve her bir sistem için özel zeka üretilmesine yardımcı olur. O halde, bir sistem, başka bir sistemden elde edilemeyen bilgiler nedeniyle fidye olarak tutulamaz.

  5. Daha hızlı geliştirme ve çalışma süresi

    Burada "geliştirme zamanı" terimini kullandım, ancak "hata ayıklama zamanı" kullanmak daha uygun olacaktır. Herhangi bir yeni gelişme gerçekleştiğinde, gerekli verilerin kendi karmaşıklığını eklemeden mevcut olması daha hızlı olacaktır, çünkü o zaman nispeten daha küçük hata ayıklama döngüleri olacaktır.

    Sizden yarım ay önce belirli bir ayda günlük indirimler için talep üzerine raporlar oluşturmanız istendiğini düşünün. Orijinal fiyatınız varsa, sipariş, sipariş öğesi ayrıntıları ile birlikte 1-2 tabloda indirimli fiyat, bu hemen hemen düzdür. Ancak, başka bir tablodan fiyatları alıp getirmeniz ve ardından başka bir tablodan geçerli indirimler yapmanız ve ardından ayrıntıları anlamanız gerekiyorsa, hem geliştirme hem de çalışma süresi daha yüksek olacaktır.

İyi bir tasarım, şimdiki zaman için olması gerektiği gibi, gelecek için de optimize etmeye çalışmalıdır.


2

Depolamada daha pahalıya mal olabilir, ancak satışın tüm ilgili ayrıntılarını işlemin kendisiyle birlikte barındırmayı tercih ederim, böylece herhangi bir nedenle denetim izimiz bozulursa veya bir yönetici yerinde güvenlikleri geçersiz kılarsa, satış gibi: kullanılan para birimi, birim fiyat, adet, uygulanan vergiler ve geldikleri değer, vb. hepsi mevcuttur. Ben genellikle XML olarak depolamak böylece satıştan satışa esnek olabilir.


DÜZENLEME: Yukarıda kısaca söylediklerimi, aşağıdaki takip yorumumda ve @a_horse_with_no_name'nin yukarıda değindiği şeyleri genişletmek için, işlem verilerinde fazlalık sadece önemli değil, aynı zamanda ölçek olarak da gereklidir.

Ben OOP kullanarak inşa varsayıyorum ve bu yüzden muhtemelen bir işlem nesnesi ve tüm kapsayan bir ürün nesnesi ve / veya bir fiyat nesnesi olması gerekir. Kendi kişisel deneyimime göre, tarihimde ayrıntılı olmayı tercih ediyorum, depolama nispeten cıvıltı.

Yaptığımız şey, mevcut bir RDBMS'nizi veya NOSQL anahtar değeri deposunun (ya da handlersocket veya memcache gibi NoSQL benzeri bağlantılara izin veren bir RDBMS'nin daha iyi bir çeşidi) kullanmayı kolaylaştırabileceğiniz bir nesne geçmişi oluşturmaktır ve nesne geçmişini saklarız bu şekilde, her ayrıntı ve fiyat değişikliği ile tek bir yerde kolay ve hızlı bir şekilde kullanılabilir. Ciddi iseniz, DIFF'leri depodan tasarruf etmek için kullanabilirsiniz ve kendi uyarıları olmasına rağmen değişiklikleri sadece ileriye saklayabilirsiniz. Bu, geçmişinize dikkat etmeli ve serileştirilmiş nesnelerin avantajı, sisteminizin bunları depolandıkları nesneler olarak geri getirebilmesidir. Bu tarihle ilgilenir.

Benim önerim ile ilgili olarak, vergiler, para birimi, vb. uygun gördüğünüz gibi değişen veriler. Anlık görüntüye hızlı erişim elde edersiniz ve yedekli ve doğrulanabilir kayıtlardan ek fayda elde edersiniz.

Buna değer, güven bana!


bu, silinebileceği için kullanmadığınızı söylemek gerçekten mantıklı değil. Herhangi bir veriyi geçersiz kılabilirsiniz. Herhangi bir strateji yedek
tutmalıdır

@Gaz_Edge Onlar birbirini dışlamazlar, yine de bir denetim izi kullanabilir ve ayrıntıları işlemlerle birlikte saklayabilirsiniz, bu durumda fazlalık haklıdır. Kendinizi asla bu önemli noktaya maruz kalan verilerle birlikte bırakmayın. Bizim durumumuzda, nesne türü başına bir tarih oluşturmaya çalışmak yerine, bu durumda bir işlem veya ürün gibi, merkezi bir nesne deposunu tarih mekanizması olarak kullanıyorum. Tarihte hem işlem nesnesinin tamamı hem de kaydın kendisiyle ilgili en önemli ayrıntılara sahip olacağım. Bu tamamen tarihteki ürün nesnelerini bir kenara bırakır.
oucil

ya siparişlerle ilgili raporlar çalıştırmak istersem ne olur? Kaç tane x ürünü satın alınmış gibi? Ya da y üzerinden kaç sipariş var? XML olarak kaydetmek, yanlış olmadıkça verileri sorgulama yeteneğini kaybettiğiniz anlamına gelir
Gaz_Edge

@Gaz_Edge Doğru değil, MySQL'den konuşuyorsanız, SELECT ExtractValue(field_name, '/x/path/');belirli bir para birimindeki tüm işlemler veya belirli bir asgari vergi değerine sahip tüm işlemler veya herhangi bir şey için filtre uygulayabilirsiniz . Nesne geçmişinden daha büyük ölçekli raporlar yapılabilir. Daha büyük ölçekli raporlar için elasticsearch, BigData stil raporlamasına sahip bir sunucu / sunucu oluşturabilir ve milyonlarca dokümana + kolayca ölçeklenebilir.
oucil

@Gaz_Edge Ayrıca bahsetmeliyim ki, bahsettiğiniz raporlar (değer üzerinden satın alma, ürün satışı, vb.) Yaygın raporlardır ve daha hızlı işlem için işlem kaydıyla sütun değerleri olarak depolanmış değerlere sahip olmalıdır. Önemli ancak zorunlu olarak rapor edilmeyen her şey XML'e girebilir. Anlık görüntü verileri yalnızca iki şey içindir: 1. Yavaşça Değişen Boyut sorunu ve 2. Müşteri şikayet ettiğinde doğrulama ve karşılaştırma ve kimin doğru olduğunu hızlıca görmeniz gerekir. Günlük kullanım için değil.
oucil

1

Benim oyum, birim fiyatını satır öğenizde saklamak ve ürünlerinizin fiyatlandırma geçmişini ayrı bir tabloda izlemek olacaktır. Bunun gerekçesi daha fazla esneklik için.

Fiyatlandırma yapınız katı ve iyi tanımlanmış ve @Chris Saxon'un yukarıda belirtilen varyasyonlara izin vermese bile, her zaman bu şekilde olacağı konusunda rahat mısınız? Emin olsanız bile, neden kendinizi bir köşeye boyadınız? Bunu satır öğesi detayında saklamanın iyi bir fikir olacağını düşünüyorum çünkü ayrı tutmak için zorlayıcı bir neden düşünemiyorum.

Fiyatlandırma geçmişinizi saklamak için, bir ürünün fiyatında değişiklikler olabileceğinden ve hiç kimse satın almadığından, bunu ayrı olarak saklamanın kesin bir değeri vardır. Bu, bir fiyat değişikliğinin etkisiz olup olmadığını bilmek için kesinlikle yararlı bilgiler olacaktır. Bahsettiğiniz gibi, bu bir veri ambarı senaryosunda Tip 2 Yavaşça Değişen Boyutun klasik bir kullanım örneğidir. Genellikle ürün tablonuzdaki herhangi bir fiyat değişikliği yakalanır ve boyut tablosuna güncellenmiş fiyat ve bu değişikliğin ne zaman gerçekleştiğini gösteren bir zaman damgasıyla yeni bir satır eklenir. Önceki satır, artık geçerli fiyat olmadığını belirtmek için bitiş tarihini güncellemiştir. Dolayısıyla bir yaklaşım, veri ambarındaki bu tür değişiklikleri izlemek olacaktır.

Ancak, OLTP e-ticaret veritabanınızı tasarlarken aynı zamanda bir veri ambarı şeması ve ETL işlemi tasarlamakla ilgilenmek istemiyorsanız, bu geçmiş kesinlikle e-ticaret veritabanımızda yakalanabilir. Bu, ürün tablosundan sarkan ve bir ürünün o sürümünün geçerli olduğu başlangıç ​​ve bitiş tarihlerini içeren ayrı bir product_audit tablosu oluştururken açıkladığınız şekilde yapılabilir. Şu anda hangi ürünün aktif olduğunu göstermek için tabloya başlangıç ​​ve bitiş tarihleri ​​eklenerek ürün tablosunda da yapılabilir. Ancak, ürün sayısına ve şirketinizin maruz kaldığı sayı veya fiyatlandırma değişikliklerine bağlı olarak, bu ürün tablonuzun tasarlandığından daha büyük olmasına neden olabilir ve daha sonra sorgu performansı sorunlarına neden olabilir.

Son olarak, fiyatlandırma geçmişinizi satır öğesindeki gerçek birim fiyattan ayırmak, bir ürünün o sırada listelenen fiyatın üstünde veya altında bir fiyata ne zaman satıldığını görmek için kesinlikle başka analitik fırsatlar verebilir.


Cevap için teşekkürler. Bence birlikte gideceğim strateji, kitap başına OLTP'yi tasarlamak olacak. Aslında raporlama için bir veri ambarına sahip olma fikrini seviyorum. Bazı ek çalışmalar eklese de (yeni bir şema oluşturma) şema OLAP'a uyarlanabilir. Yuvarlak bir deliğe kare bir saplama takmaya çalıştığım bir senaryodan kaçınmak gibi.
Gaz_Edge

@Gaz_Edge: Yeni projeme karar vermek konusunda benzer bir durumdayım. Bir yıl önce hangi tasarım yaklaşımını aldığınıza dair düşüncelerinizi paylaşmak ister misiniz? İyi çalıştı mı?
Kodlayıcı Mutlak

@CoderAbsolute benim orijinal çözüm çok 'veritabanı' yönelimli idi. Uygulamam şimdi Servis Odaklı Mimari etrafında toplanıyor. Şimdi bir sıkı sıkıya bağlı bir yerine birçok küçük ayrıştırılmış veritabanı şemaları var. Büyük bir şemada 3N'ye olan ihtiyaç artık ortadan kalktı. Şimdi birim fiyatı doğrudan siparişe ekliyorum. Tarihi ürün fiyat değişikliklerini korumak artık bir iş gereksinimi olmadığı için ortadan kalktı. Umarım yardımcı olur.
Gaz_Edge

0

Siparişle ilgili bilgileri (bağlamı) bir arada tutma temel fikrine tamamen katılıyorum. Sadece küçük bir yan not böyle bir durum sadece uygulama çok veritabanı merkezli tasarlarken ve her şey büyük yağ db etrafında döner zaman ortaya çıkacaktır. Bakış açınızı sorun alanına farklı bir açıdan bakarak değiştirirseniz, siparişin uygulamanızın yaşam döngüsünde çok özel bir olayın yakalanmış bir anlık görüntüsü olduğunu açıkça göreceksiniz. Bağlama dayalı sorunları ele aldığınızda, veritabanı sorunları ikincil hale gelir ve herkes sorgulama ve rapor oluşturma konusunda korktuğu karmaşıklık, etki alanı modelinde sorunsuz bir şekilde işlenir.


Bazı küçük örnekler cevabınızı anlamayı kolaylaştıracaktır. Özellikle 'sipariş, uygulamanızın yaşam döngüsünde çok özel bir olayın yakalanmış bir görüntüsüdür' gibi cümleler.
dezso
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.