在營銷的場景裡有三要素
- 使用者
- 商品
- 優惠
在這三個要素裡,再加一些如時間,數量,頻次等變數,會演化出各種組合,使得業務變得非常靈活。各業務線為了滿足業務,一般都會各自實現,且多數情況下都會重複實現,而且實現起來各地方都會產生交叉配置,交叉互斥的問題。在觀察到這些問題後,總結並嘗試用一個計數頻次中介軟體形態的系統統一解決。一是解決了複雜度、重複建設;二是統一處理後,資料層面上將整體打通,對於使用者監控、風控、特徵、行為上提供完整資料。
在電商的系統中,有商品、使用者、優惠三種要素。這三種要素分別在數量,時間,頻次上又有多維度的分類。
如商品限量100份(數量)對使用者每天(時間)每人購買限量2份(頻次),按這種規律下,使用者使用優惠也同樣遵循這種規則,即
優惠券總數100張(數量),使用者每場(時間)可使用1張(頻次)
抽獎優惠也一樣,即
優惠總數100張,使用者每天(時間)可領取1張(頻次)
發放優惠也一樣,即
優惠總額100元,使用者每天(時間)可優惠1次(頻次)
分類法
- 按主體,維度分類
主體\維度 | 數量 | 時間 | 頻次 |
---|---|---|---|
商品 | 總數 | 指定週期,天,小時,周 | 不限,1份,多份 |
使用者 | 總數 | 指定週期,天,小時,周 | 不限,1份,多份 |
優惠 | 總數 | 指定週期,天,小時,周 | 不限,1份,多份 |
活動 | 總數 | 指定週期,天,小時,周 | 不限,1份,多份 |
按上面這個分類,主體會變,維度會變,先設計領域模型,分別為實體(entity);維度(dimensions);實體維度關係(entityDimensionsRel),關係領域將表示,主體將擁有多個維度,並在多個維度中設定維度值,如商品每天限購1份,那麼將在entityDimensionsRel中的limit_value中設定1,time_interval設定為1天
領域模型
資料模型
資料庫表模型
- 主體表 (Entities)
- EntityID: 主鍵,唯一標識某個主體(如商品、優惠、活動等)
- EntityType: 主體型別(如商品、優惠、抽獎等)
- EntityName: 主體名稱
CREATE TABLE Entities (
EntityID INT PRIMARY KEY,
EntityType VARCHAR(50),
EntityName VARCHAR(100)
);
- 維度定義表 (Dimensions)
- DimensionID: 主鍵,唯一標識某個維度(如數量、時間、頻次)
- DimensionName: 維度名稱(如“數量”、“時間”、“頻次”)
- DimensionType: 維度型別(如整數、日期、時間區間等)
CREATE TABLE Dimensions (
DimensionID INT PRIMARY KEY,
DimensionName VARCHAR(50),
DimensionType VARCHAR(50)
);
- 主體-維度關係表 (EntityDimensions)
- EntityDimensionID: 主鍵,唯一標識某個主體-維度關係
- EntityID: 外來鍵,關聯到Entities表
- DimensionID: 外來鍵,關聯到Dimensions表
- LimitValue: 該維度的限制值(如限量、限次等)
- TimeInterval: 時間間隔(如每天,每場活動等),適用於時間維度
CREATE TABLE EntityDimensions (
EntityDimensionID INT PRIMARY KEY,
EntityID INT,
DimensionID INT,
LimitValue INT,
TimeInterval VARCHAR(50),
FOREIGN KEY (EntityID) REFERENCES Entities(EntityID),
FOREIGN KEY (DimensionID) REFERENCES Dimensions(DimensionID)
);
上面這些表可以完整記錄主體在各維度的限制值。還需要一張實時記錄主體資料在各維度的過程資料
- 例項資料記錄表 (EntityDimensionRecords)
- RecordID: 主鍵,唯一標識某條記錄
- EntityID: 外來鍵,關聯到Entities表
- DimensionID: 外來鍵,關聯到Dimensions表
- UserID: 外來鍵,關聯到使用者表(適用時)
- Value: 在該維度上記錄的數值
- RecordDate: 記錄的日期或時間。
CREATE TABLE EntityDimensionRecords (
RecordID INT PRIMARY KEY,
EntityID INT,
DimensionID INT,
UserID INT,
Value INT,
RecordDate DATETIME,
FOREIGN KEY (EntityID) REFERENCES Entities(EntityID),
FOREIGN KEY (DimensionID) REFERENCES Dimensions(DimensionID)
);
資料流轉
樣例1
使用者參與大轉盤活動,活動週期內只能抽一次獎
主體:大轉盤活動
維度:時間,計數
關係:限制值(一次);限制時間(活動週期);
簡單填入資料,業務就可以滿足了。
現在又有新的業務需求,即這個活動週期為1個月,使用者每天都要能參與一次,現有的表模型就不支援了!
關係表(EntityDimensions)的時間欄位TimeInterval是個varchar,表示1天、1小時等列舉值是可以,如果表示時間段,每天等帶頻次的複雜時間是不夠的,所以,最好的辦法之一就是將時間維度拆出一張表
CREATE TABLE TimePeriods (
TimePeriodID INT PRIMARY KEY,
PeriodName VARCHAR(50),
TimeInterval VARCHAR(50), -- 時間週期(每天、每小時、每半小時、每分鐘)
StartTime TIME, -- 時間段開始時間
EndTime TIME -- 時間段結束時間
);
有了這張表後,就可以表示週期時間段的計數關係了。
有了這張表後,業務在查詢EntityDimensionRecords,就知道這條記錄的週期,開始時間結束時間。
如果時間頻次TimeInterval是天,當前時間為2022-12-12時,EntityDimensionRecords.RecordDate值為2022-12-11時,那麼EntityDimensionRecords需要重新生成一條記錄,並且RecordDate值為2022-12-12;
越往深入,能夠列舉出的維度是有限的,在大的方向上,每一個維度也可以拆分出一個領域也是可行的。因為維度值不一樣,單純用維度一個變數有點滿足不了需求,如時間維度和數量維度,維度值用一個變數就表示不了,時間範圍最少需要2個欄位。所以在不同的業務發展時期,只有當時最合適的設計,沒有永遠對的設計。在考慮擴充套件性的同時,也需要考慮研發成本。
如果以後有需求對計數的方式有變化,比如一次計數消耗2次機會,那相應的,再在EntityDimensions.LimitValue欄位上做一個新表來表示計數的複雜方式。萬變不離其宗,好的設計一定是支援業務慢慢成長起來的。糟糕的設計是不停的妥協設計,隨著時間推移開發和維護將會越來越困難!