Tinder 數(shù)據(jù)庫(kù)模型

假設(shè)有一個(gè) User 表和一個(gè) Match 表。那么 Match 表應(yīng)該如何安排結(jié)構(gòu)呢?假設(shè) db 在記錄 John 和 Jane 之間的交互。會(huì)有一個(gè)基礎(chǔ)(base)用戶列和一個(gè)目標(biāo)(target)用戶列嗎?John 右滑了 Jane(一行)然后 Jane 右滑了 John(一行)所以總共是兩行?或者它是不是應(yīng)該設(shè)計(jì)為一行呢?一行設(shè)計(jì)意味著,沒(méi)有基礎(chǔ)用戶和目標(biāo)用戶,而是會(huì)有 user1 和 user2。jane 和 john 的位置最終會(huì)隨機(jī)決定。

兩行設(shè)計(jì):

Base User | Target User | Liked

row1 John|Jane|YES|YES
row2 Jane|John|YES|YES

一行設(shè)計(jì):

User1 | User2 | User1_Liked_User2 | User2_Liked_User1 | Match

row1 John|Jane|YES|YES|YES

我知道如果是一行設(shè)計(jì),缺點(diǎn)就是,要獲取 john 的配對(duì)數(shù)量需要看 user1 user2 兩列,但如果是兩行設(shè)計(jì)你只需要搜索 base user 行。

盡管一行處理方式可以省去一半的行數(shù),但表現(xiàn)會(huì)不會(huì)更好呢?或者說(shuō)現(xiàn)在 w/ dbs 的擴(kuò)展性已經(jīng)很強(qiáng)了,有沒(méi)有什么我們能忽略的呢?

為了論證,假設(shè)用戶數(shù)為 10 萬(wàn)。


如果 Tinder 在使用 RDBMS 的話……我想每個(gè)用戶被關(guān)聯(lián)到一個(gè)滑動(dòng)為 LIKES 和一個(gè)標(biāo)記為 IS_LIKED 都會(huì)有一條記錄。這種方式你可以拉出一個(gè)用戶記錄 (SELECT * FROM MATCH WHERE USER_ID = X) 然后回答所有關(guān)鍵問(wèn)題:

  • 用戶喜歡誰(shuí)?(LIKES = TRUE)
  • 誰(shuí)喜歡了用戶?(IS_LIKED = TRUE)
  • 誰(shuí)是用戶的配對(duì)?(LIKES = TRUE and IS_LIKED = TRUE)

當(dāng)一個(gè)滑動(dòng)發(fā)生的時(shí)候,你合并了 2 個(gè)新的記錄到已經(jīng)存在的數(shù)據(jù)中。如果記錄是新的,只是一個(gè)直接插入。如果是一個(gè)更新,更新一個(gè)記錄的 LIKES 和另一個(gè)的 IS_LIKED 然后糾結(jié)了。

你可以給一個(gè)表只寫 “l(fā)ikes”,然后用一個(gè)介于兩個(gè)用戶之間的查詢來(lái)判斷 match,當(dāng) row 的數(shù)量為二的時(shí)候。這樣會(huì)導(dǎo)致更少的寫入,更小的索引,減少偏航(drift)的機(jī)會(huì)?

你是不是說(shuō)如果不是 RDBMS,設(shè)計(jì)會(huì)不同?

當(dāng)然。一個(gè)鍵值庫(kù)或 ORDBMS 可能需要一個(gè)不同的設(shè)計(jì)來(lái)有效的杠桿數(shù)據(jù)。


通常的,你會(huì)想要追蹤更多的信息,不只是 yes 或 no。例如,你應(yīng)該想要這個(gè)人滑動(dòng)的日期/時(shí)間。當(dāng)你有更多數(shù)據(jù)和滑動(dòng)相關(guān),用一行設(shè)計(jì)就越來(lái)越不實(shí)用了。

為了查詢的簡(jiǎn)單,你可以添加一個(gè) “swipe_from_other_was”,但查看一個(gè)特定滑動(dòng)的細(xì)節(jié)的時(shí)候,那它都會(huì)在一行里,對(duì)于另一個(gè)人的細(xì)節(jié),會(huì)在另一行里。

側(cè)面說(shuō)明一下,Match 會(huì)是那個(gè)表很爛的名字,Swipe 對(duì)于它的目標(biāo)來(lái)說(shuō)是更清晰的。

如果是這樣的話,要查詢 “John” 配對(duì)的數(shù)量不會(huì)變的太重了嗎?如果 John 右滑了 1000 人,然后我們要做一個(gè)次級(jí)查詢 FROM 一千人?;蛘吣阍诮ㄗh給 Match 一個(gè)單獨(dú)的表?一旦 john 喜歡了 jane,jane 喜歡了 john,Match 表插入一行?

我的第二段就是特別說(shuō)這個(gè)需求的。你可以添加一列,簡(jiǎn)單地說(shuō),如果 “target user” 也喜歡了 “base user”。基本上,有一個(gè)滑動(dòng)的時(shí)候,你為那個(gè)滑動(dòng)創(chuàng)建了一行,帶著所有相關(guān)數(shù)據(jù),然后在表里查詢另一個(gè)人的滑動(dòng),如果找到了,你在現(xiàn)有的和在新的行中更新額外的列會(huì)是正確的。這種方式你可以快速運(yùn)行分析或任何你需要做的事情。

側(cè)面說(shuō)明,一個(gè)相當(dāng)簡(jiǎn)單地 select 會(huì)給出這個(gè)信息。帶有正確的索引的話會(huì)相當(dāng)快,否則用 2 個(gè)查詢來(lái)做也可以。

SELECT other_swipe.base_user
FROM swipe
JOIN swipe other_swipe ON swipe.base_user = other_swipe.target_user
WHERE swipe.base_user = *John's id* AND swipe.liked = TRUE AND other_swipe.liked = TRUE

為什么不簡(jiǎn)單點(diǎn):

UserId ShownUserId Liked
John Jane yes
John Jill no
Jane Dave yes
Jane John yes
Jill Dave no
Jill John yes

John 喜歡誰(shuí):

select ShownUserId from UserLikes where UserId = 'John' and Liked = yes

誰(shuí)被 John 喜歡了而且也喜歡回了他:

select UserLikes.ShownUserId 
from UserLikes
    inner join UserLikes as AlsoLikesMe
        on UserLikes.UserId = AlsoLikesMe.ShownUserId
        and AlsoLikesMe.Liked = yes
where UserLikes.UserId = 'John' and UserLikes.Liked = yes

不要忘記 ShownUserId 上的索引。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容