緩存遇到的數據過濾與分頁問題

遇到的問題

一、最初階段

系統中作了一個監控功能,用於記錄全部的請求數據,數據插入頻繁,量很是大,好比一天1000萬條。考慮到數據插入的效率,就使用內存KV緩存來保存。寫入過程是在接收到請求後放入到線程池中,而後線程池異步處理後寫入。到這問題基本上沒什麼事情。mysql

二、新的需求

後面數據保存了,就須要在運維繫統中能夠查詢到,因此這個緩存還必須是分佈式的。因而就換成了redis,這樣系統均可以鏈接到。可是數據量太大,須要分頁查詢,這就有點頭痛了。還好redis是能夠支持有序集合的,並且能夠經過zrange來獲取指定範圍數據。redis

三、增長了需求

這些數據要在運維界面裏還要能夠按條件過濾,這個就很是頭疼啦,redis沒有條件過濾啊。即便過濾出來了數據要顯示在界面上必須分頁。sql

問題思考

最終忽然發現若是存在數據庫裏是否是很好解決?可是存在數據庫裏就會有大量寫操做的問題,並且數據這麼大,像Mysql單表很容易就破了。因此我想着是否是仍是在nosql的基礎上解決。數據庫

這裏就有幾個問題:大數據量的排序、查找過濾、分頁。緩存

先無論這麼多,若是使用Mysql的話,除了大表保存問題,查找、過濾、分頁功能都是直接使用sql實現的,開發起來簡單。運維

mysql

若是使用mysql存儲後,若是要查一些數據怎麼整?先看下面的這段代碼:異步

SELECT t.* 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,100

這裏最直接的就體現了兩點:先排序,而後取分頁的數據。好了,這裏有幾個問題:nosql

一、使用了*返回字段,全字段返回的問題就是要掃描全表
二、進行了ORDERBY排序,我測試的這個表只有幾百萬數據
三、最後分頁是取的130萬開始的100條,等因而要掃描130萬後纔開始分佈式

我隨便跑了一下執行了:5.5秒左右。有沒有辦法讓它快一點呢?確實有,網上找找挺多的。性能

首先,看看只返回部分字段是否是快一些?

SELECT t.creationDate 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,100

上面的SQL語句,改造後,只返回一個字段,再執行。2.9秒了。

那麼取1條數據的速度會不會快一些呢?

SELECT t.creationDate 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,1

執行上面的sql後發現時間仍是2.9秒,這說明取1條的數據也是這麼慢,那慢的確定就是排序啦。

而後使用這一條取出來的數據做爲條件,直接在集合中定位到分頁數據

SELECT ofOffline1.* FROM ofOffline1 WHERE ofOffline1.creationDate <(
SELECT t.creationDate 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,1
) 
ORDER BY ofOffline1.creationDate desc
LIMIT 100

這是網上查到的SQL,思路就是先使用子查詢定位到第130萬條記錄,而後從它開始取後面的99條。時間差很少3.9秒左右。這說明這樣的優化仍是有效的。

使用一下索引
我想了想若是加個索引是否是能夠提高性能呢?SQL中只使用了creationDate排序和過濾,那麼就用它建個索引試試吧。

仍是測試一下最簡單的那條SQL

SELECT t.* 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,100

結果是:5.5秒左右,沒變化

那麼看看前面有子查詢的狀況:

SELECT ofOffline1.* FROM ofOffline1 WHERE ofOffline1.creationDate <(
SELECT t.creationDate 
    from ofOffline1 t 
    ORDER BY t.creationDate desc
  LIMIT 1300000,1
) 
ORDER BY ofOffline1.creationDate desc
LIMIT 100

不錯,執行結果:0.599秒。

好吧,本文先到這,後面再學習一下mangodb,按理它會比較適合咱們的場景。

相關文章
相關標籤/搜索