我是這樣優化用戶關係查詢的

0x01

咱們有一個業務場景是須要將用戶邀請的下級用戶根據其用戶等級給統計出來(不止統計一級).
現有的解決方案:
mysql中一張用戶表
主要的3個字段:user_id, parent _id,level,
典型的一個樹形結構.
由於數據量很大,查詢次數不少,因此重算這數據基本上重算一次要花個幾分鐘.mysql

0x02

優化版本1:
假如我將沒全部用戶對應的全部直接下級用戶的id取出,存放到redis中的數組,像這樣redis

U:110->[111,112,113,...] sql

將用戶等級也放到redis中,像這樣 數組

L:110->0 優化

而後經過map的方式取到下級的下級用戶併合並起來,再經過用戶等級進行分組。code

users.stream.map(u-> jedis.lrange(0,-1)).flatMap(u-> u).collect(grouppingBy(u-> jedis.get("L:" + u)))... 內存

LRANGE
時間複雜度:O(S+N), S 爲偏移量 start , N 爲指定區間內元素的數量。`
優化結果:
計算機器:I5 六代 8G內存
時間:25秒get

0x03

優化版本2:
使用Set存放用戶,經過SUNION命令獲取下級IDio

時間複雜度:O(N), N 是全部給定集合的成員數量之和。stream

獲取當前下級的用戶代碼則更簡單了,首先將當前用戶經過CPU並行的方式把SET的key計算出來,而後經過SUNION將全部的用戶取出來:

private Set<String> downLevelAllUser(Set<String> users) {
    return jedis.sunion(users.parallelStream().map(s ->
            "U:" + s
    ).collect(Collectors.toList()).toArray(new String[0]));
}

這些用戶的等級都查出來,那就獲取他們的用戶等級並進行分組.

private Map<String, List<String>> groupUser(Set<String> users) {
    return jedis.mget(users.parallelStream().map(u -> "L:" + u)
            .collect(Collectors.toList()).toArray(new String[0]))
            .parallelStream().collect(Collectors.groupingBy(r -> r));
}

主要功能都實現了,那麼試試計算8級所花時間

public List<Map<String, Integer>> downLevel8UserRole(int start_user) {
        Set<String> u1 = downLevel1Users(start_user);
        Map<String, List<String>> m1 = groupUser(u1);
        Set<String> u2 = downLevelAllUser(u1);
        Map<String, List<String>> m2 = groupUser(u2);
        Set<String> u3 = downLevelAllUser(u2);
        Map<String, List<String>> m3 = groupUser(u3);
        Set<String> u4 = downLevelAllUser(u3);
        Map<String, List<String>> m4 = groupUser(u4);
        Set<String> u5 = downLevelAllUser(u4);
        Map<String, List<String>> m5 = groupUser(u5);
        Set<String> u6 = downLevelAllUser(u5);
        Map<String, List<String>> m6 = groupUser(u6);
        Set<String> u7 = downLevelAllUser(u6);
        Map<String, List<String>> m7 = groupUser(u7);
        Set<String> u8 = downLevelAllUser(u7);
        Map<String, List<String>> m8 = groupUser(u8);
        return Arrays.asList(m1, m2, m3, m4, m5, m6, m7, m8).parallelStream().map(m -> {
            Map<String, Integer> newMap = new HashMap<>();
            m.forEach((k, v) -> newMap.put(k, v.size()));
            return newMap;
        }).collect(Collectors.toList());
    }

優化結果:
總用戶數爲:120W
計算機器:I5 六代 8G內存
時間:4秒

好了,優化完畢了,大神們還有什麼高招,歡迎來指導!!!!!!

相關文章
相關標籤/搜索