溫馨提示
周末菜菜送的書,你領了嗎?沒領的話,關注公眾號之后參加活動哦!
菜菜哥,我又讓領導罵了


來,哥安慰一下你,說說你挨罵的原因,讓哥樂一樂


....是這樣的,我做的商城有一個訂單統計的功能,我除了記錄訂單之外,還記錄了下單人的信息,其中有省市區縣id的信息


傾聽中.......


然后業務部門會有根據區域(省市區縣)訂單的各種統計需求,比如xx省的訂單數,訂單總金額等統計。


傾聽中...


由於人員的區域信息可能會變動,用戶區域信息就算是同步或者不同步都會出現差錯


每個用戶信息只存在一條記錄?


是的。比如用戶A現在屬於省id為1000的省,生成了一個訂單,這個省的訂單數統計會加1,假如訂單總數變為了20001,然后用戶A所屬的省的Id變為了1001,那Id是1000的省的訂單總數又變成了20000


我明白你的問題了,來,妹子,哥給你好好說說這個事



請不要跟我說用ES或者其他,其實很多中小公司的業務就是如此,就是基於mysql或者sqlserver 來搞這樣的業務


不知道通過D妹子的闡述,大家了解情況了沒。這里菜菜再詳細說一下。D妹子的程序記錄了訂單的log來供其他業務(比如統計)使用,這里就以統計業務來說,OrderLog表設計如下:
列名 | 數據類型 | 描述 |
---|---|---|
OrderId | nvarchar(100) | 訂單號,主鍵 |
UserId | int | 下單用戶id |
Amount | int | 訂單的金額 |
其他字段省略... |
除此之外還有一個用戶信息表UserInfo,設計如下:
列名 | 數據類型 | 描述 |
---|---|---|
UserId | int | 用戶id,主鍵 |
ProvinceId | int | 用戶省的id |
CityId | int | 用戶市的id |
CountyId | int | 用戶區縣的id |
涉及到拆單等復雜的訂單操作,表的設計可能並非如此,但是不影響菜菜要說的事

現在假如要統計某個省的訂單總數,sql如下:
select count(0) from OrderLog o inner join UserInfo u on o.UserId=u.UserId where ProvinceId=@ProvinceId
有問題嗎,sql沒問題,這時候用戶A的省市區縣信息突然變了(也許是在其他地區買房,戶口遷移了),也就是說UserInfo表里的信息變了,那用以上的sql統計用戶A以前省市區縣的訂單信息是不是就會出錯了呢?(產品狗說在哪下的訂單就屬於哪的訂單)

以上的問題你覺得是不是很簡單呢?只要稍微修改一下表也許就夠了。但是,菜菜要說的不是針對這一個業務場景,而是所有的業務場景的設計。那你有沒有想過為什么D妹子的設計會出現這樣的問題呢?
深刻理解業務才能避免以上類似的錯誤發生,一定要深刻理解不變和可變的業務點。 拿D妹子的統計來說,你的業務是統計區域的訂單數,這個業務在產品設計上定義的是不變性,也就是說在行為產生的那個時間點就確定了業務性質,這個業務的性質不會隨着其他變而變。具體到當前業務就是:用戶在X省下的訂單不會隨着用戶區域信息的變化而變化,說白了就是說用戶在X省生成的訂單永遠屬於X省。
談到業務性質的不變性,對應的就有業務的可變性。假如你開發過類似於QQ空間這樣的業務,那肯定也做過類似訪客的功能。當要顯示訪客記錄的時候,訪客的名稱在多數情況的設計中屬於可變性的業務。什么意思呢?也就是說一個用戶修改了姓名,那所有顯示這個用戶訪問記錄的的地方姓名都會同時改變。
說到這里,各位再回頭看一下D妹子的業務,這里又牽扯到一個系統設計的問題,眾所周知,一個好的系統設計需要把業務的變化點抽象提取出來,D妹子訂單統計的業務變化點在於用戶的省市區縣會變化,訂單的金額、訂單號等信息不會變化。所以你們覺得是不是D妹子的數據表可以修改一下呢?
數據表的改進
01
按照以上的闡述,D妹子業務的變化點在於用戶的省市區域信息,所以可以把用戶信息的表抽象提取出來,主鍵不再是用戶id
列名 | 數據類型 | 描述 |
---|---|---|
Id | int | 主鍵Id,主鍵 |
UserId | int | 用戶id |
ProvinceId | int | 用戶省的id |
CityId | int | 用戶市的id |
CountyId | int | 用戶區縣的id |
這樣的話用戶訂單log表中就變為
列名 | 數據類型 | 描述 |
---|---|---|
OrderId | nvarchar(100) | 訂單號,主鍵 |
UserBId | int | 對應用戶表中的主鍵id |
Amount | int | 訂單的金額 |
其他字段省略... |
這樣設計的話,如果用戶的省市區縣信息有變動,相應的用戶信息表中會存在多條用戶省市區縣數據


02
根據業務的變性和不變性,既然把訂單區域統計的業務定義為不變的業務性質,那訂單的log表完全可以這樣設計
列名 | 數據類型 | 描述 |
---|---|---|
OrderId | nvarchar(100) | 訂單號,主鍵 |
UserId | int | 下單用戶id |
ProvinceId | int | 用戶省的id |
CityId | int | 用戶市的id |
CountyId | int | 用戶區縣的id |
Amount | int | 訂單的金額 |
其他字段省略... |
各位讀到這里,可能會感覺菜菜這次寫的其實很雞肋,但是,D妹子的場景卻是真實環境中遇到的問題。問題的本質還是變性業務和非變性業務的定義和划分,和架構設計一樣,數據庫的設計其實也需要把變動的業務存儲點進行抽象,其實應該說是抽離出來。
希望大家有所收獲 --菜菜
互聯網之路,菜菜與君一同成長
長按識別二維碼關注

