什麼是分區數據?若是一張表被水平切分,好比切分紅100張相同的表。經過sharding策略把數據分別存放在這100張表中,那麼稱這100張表的每一張表爲一個分區。它們共同組成了這個同類型的數據表。 sql
提供一個例子供之後分析 如: 數據庫
1,user表分紅100個region 架構
2,sharding策略:按照user_id%100決定放到哪一個分區。 性能
3,user表有一個age字段 spa
若是分區的sharding策略不是按照某個條件作的range分區。上面例子就明顯不是按照user_id的range分區。若是要對例子中的user作以下查詢。 內存
select * from user where age>10 order by age limit 100; it
對於這個查詢,要對這100個表作merge而後取出100條(若是存在100條); io
做者以及做者以前的一些同事,覺得對於這種merge須要每一個region取出100條,而後merge sort,最終取出100條。那麼就是在上面的top100也須要查詢100*100到內存(假設region數據有足夠多),想一想,若是取的不是top100,而是一直向下翻頁,那麼將是timeout 和oom的競爭。上週週末公司邀請了一位淘寶牛人作互聯網架構分享,竟然他們以前region merge也是這樣作的。因此決定把在讀hbase代碼時發現的優秀方案分享一下。hbase scan時須要memstore和storefile作heap merge。 原理
利用分區有序。 file
如上個場景能夠對於,每一個region執行以下sql(主要作原理說明,至因而否是每一個region的分頁大小 region_page=10,須要根據條件給一個合理值)
select * from user where age>10 order by age limit 10;
這樣每一個region取出10條數據,總取出100條,而後對於每一個region數據進行遍歷。
遍歷方式以下:
每一個region先拿出第一條數據來比較,這一條必定是每一個region中查詢出來最小的那條數據。這樣能夠選出這100個region中最小的那條數據。不妨假設這條數據在第20這個region中,而後拿出第20這個region中的第二條數據與其餘region中的第一條數據作比較。這樣能夠選出這100個region中第二小的那條數據。依次類推,若是某個region的這10條數據都取出去了,就再拿10條。直到100條爲止。
像這樣merge
樂觀狀況: 只須要查詢100條數據就能夠找到100個有序數據
悲觀狀況: 也只須要查詢200條數據
若是須要分頁,其實就是跳過前面的頁數,好比查詢limit 100,100。那麼只須要跳過前100條,從101條開始計數便可!切記,這裏不能直接作分區分頁,分區的查詢仍是須要按照上述的查詢。不然得不到正確結果!查詢頁數越多越慢,這是必然的,RDBMS也是同樣,這是沒有捷徑的!
須要掃過的數據的計算公式以下
limit*(page) =< datas <=limit*(page+1),(page從1開始)
節省了內存,也省了數據庫查詢壓力。
固然可能要多幾回IO,這取決於每次從每一個分區取出的數據,以及limit,以及分區命中狀況
多出的IO範圍計算以下:
0=< IO_times <= limit/region_page
因此若是分頁足夠多,limit比較大region_page能夠適當調大,固然要有一個合理上限,能夠根據可用內存,以及GC狀況而定!
region_page的建議公式以下:
min(10000,limit*page)/regions=< region_page <=min(limit*(page+1),10000)/regions;
是否取region_page = min(limit*(page+1),10000)/(2*regions)比較好,呵呵,這個具體而定吧,不糾結!
利用region有序,而後對於找到值的region向下迭代。能夠找出全局順序!
須要對region page size合理計算。
可能會出現time_out,可是不會出現OOM(除非你的內存小到,只取出兩條數據就OOM了)。
這種方案在不考慮性能的狀況下,確實是能夠先從任意兩個region取出一條數據進行比較,可是這是走向time_out的節奏!