題目是一道面試題
我的想法是另起一張表,存放今天更新的10萬條都有哪些;
我只想到這個第一步,接下來該怎麼做我還不知道怎麼去實現;
假設按我這樣的思路,我就算知道了每天更新的是哪10萬條資料,那我還是得去500萬條中找出3000條資料哦
不知道各位兄弟,有啥好的想法呢?
回複內容:
題目是一道面試題
我的想法是另起一張表,存放今天更新的10萬條都有哪些;
我只想到這個第一步,接下來該怎麼做我還不知道怎麼去實現;
假設按我這樣的思路,我就算知道了每天更新的是哪10萬條資料,那我還是得去500萬條中找出3000條資料哦
不知道各位兄弟,有啥好的想法呢?
10W中的3000條,機率是3%
那麼只要在儲存文章時,按照3%的機率,把本次更新文章儲存到緩衝中
這種緩衝用redis的set類型最好,set類型不會儲存重複的元素,所以文章反覆更新也不會在列表裡面產生多個結果
key的格式可以用"analyze:list:(Y-m-d)"
然後這個緩衝可以設定為48小時到期,如果有需要的話,每天可以拿前一天的緩衝歸檔到資料庫
考慮到隨機機率的誤差,可以把3%放大到5%,最後肯定會記錄得超過3000,但是也不會超太多,反正最後只拿3000條來用就行了
把每次更新都記錄起來的話,無論是記錄到緩衝還是資料庫,其實大部分的記錄是沒用的,不如按照機率先過濾一遍
其實記錄每條文章的update_time也可以,我覺得where update_time >= ? and update_time <= ? order by random() limit 3000差不多就行了,反正每天才跑一次而已,不過既然是面試的話,怎麼能不秀秀思路呢
優點:
1、沒有update_time欄位也能玩,對現有表結構無要求,給生產環境的資料庫加欄位是件麻煩事
2、萬一生產環境的資料庫負載比較高,order by random()查詢導致資料庫卡死也不好,這樣的話,最好是讀寫分離架構,在唯讀庫上查詢才行,產生了架構要求,我這個設計完全是個旁路記錄,除了redis之外沒要求
3、需要多少才記多少,額外IO少
一些粗陋的想法,僅供參考
分區
500萬條,為了方便。根據資料的更新時間進行資料庫分區(沒用過mysql分區的看這個,在文章後面講了),
比如說按照月份,我假設你這500萬條資料是一年的,那麼分成12份,每個區大約算42萬條記錄
這樣,當使用更新時間進行搜尋的時候,mysql就會根據你的更新時間 去選擇分區,
也就是被搜尋的資料是在這42萬條裡面去找(這肯定要比你在500萬裡面快多了,當然你要是按照天來分,那會更快)
加緩衝
這沒啥,就是你每天寫入mysql的時候取3000條資料寫入redis或者mongodb裡面,做研究就不從mysql裡面讀了。用php從緩衝裡面讀
多進程
你說的要做研究嘛,我假設你的研究演算法很複雜。你去學學swoole,開三個進程,一個進程處理1000個資料,最後匯總結果
取出當日更新的10萬
id放入一個數組在數組中隨機取出3000個id
用select in讀取指定的3000條記錄
SELECT id FROM table WHERE date_refresh = 20120329SELECT * FROM table WHERE id IN (id_0, id_1, id_2, ..., id_2999)
https://www.zhihu.com/question/20151242
淺陋分析,勿笑。
1.擷取id區間
select max(id) as max_id, min(id) as min_id from ( select id from article_tb where update_time >= '2016-02-26 00:00:00')
update_time有索引,id為自增長id
2.隨機擷取
select * from article_tb where id >= min_id and id < ( rand()*(max_id-min_id)+min_id ) limit 1
查詢3000次
// STEP 1 : 擷取當天文章ID區間// maxId -> select max(id) from news where 當天時間限定// minId -> select min(id) from news where 當天時間限定// STEP 2 : 取得隨機ID// 因為你一天有10萬資料,資料總量有很高// 所以避免使用MYSQL中的隨機$minId = 5000000;$maxId = 5100000;$i = 0;$resultIds = [];while(true){ $randId = rand($minId,$maxId); if(in_array($randId, $resultIds)){ continue; } // 查詢驗證 // 根據你的需要驗證資料是否是審核的呀,是否是正常資料呀 // 如果正常就載入到結果數組中。 $resultIds[] = $randId; $i++; if($i==3000){ break; }}// 到這裡結果已經有了// 可以儲存到結果集用其他方式分頁進行研究或者瀏覽。