제2회 열린세미나 100도씨의 발표자료입니다.
Unique Count를 구하기위한 몇가지 특징과 자료구조등을 정리한 발표자료입니다.
* 열린세미나 그룹
https://www.facebook.com/groups/576473599127259/
* 블로그
http://blog.indf.net
I will make this presentation for seminar of NIPA
For more information of the seminar, please go to http://www.software.kr/user/seminar.mbs?id=swkr_050102000000&command=view&idx=376830
I will make this presentation for seminar of NIPA
For more information of the seminar, please go to http://www.software.kr/user/seminar.mbs?id=swkr_050102000000&command=view&idx=376830
"R을 이용한 데이터 처리 & 분석 실무 - 서민구 지음" 정리 자료 #3
- https://thebook.io/006723/
- 첫번째 : goo.gl/FJjOlq
- 두번째 : goo.gl/Wdb90g
- 세번째 : goo.gl/80VGcn
- 네번째 : goo.gl/lblUsR
6. * UV vs PV
UV (Unique Visitor) - 설정된 기간동안 방문한 순방문
- 해당사이트를 1회 방문하건, 10회 방문
하건, 방문자는 1로 체크
PV (Page View) - 페이지가 열린 횟수
- 구분없이 페이지가 열린 경우 카운팅 됨
PV에서는 극단적으로 1명의 헤비유저가 데이터를 훼손 할 수 있음
(새로고침으로 신공으로 PV올리기)
12. 값은 부모 단계로 승계 안되나, 부분집합형태로 구성이 가능함
집합 개념으로 보면 이해가 편함.
1
2
3
4
6
1
2
3
4
6
∪
5개 2개 3개
13. 단, 서브셋으로 구성할 때 교집합이 존재하면 안됨.
분배할때 상호배제 되어야 함.
12 3 46 1
2
3
4
6
∪
UC=5개 3개 3개
2
2
+=
14.
15. select
count(distinct 필드명) as uc
from
t_table
Set<String> set = new HashSet<String>();
set.add(“a”);
set.add(“a”); //중복
set.add(“xxx”);
set.add(“yyy”);
System.out.println( set.size() ); // print : 3
쿼리문
소스코드 (set)
16.
17. 하둡 M/R로는 UC에 적당하지 않음.
하둡은 KEY단위로 모아서 iterator<Value> 형태로 모아줌.
즉, Value에서 중복을 제거해야 하는데 사이즈가 크면 메모리가 부족함
하둡은 KEY단위로 분산을 해주는것이지
Value단위로 분산해주는것이 아님!!!!
18. 그럼? KEY 요소로 써서 카운팅 하면 되지 않을까?
가능함.
하지만 결과 파일은 중복이 제거된 값들을 결과로 받음.
즉, ‘wc –l’ 같은 명령으로 라인수를 세어야 할 것임.
그리고 더 A결과와 B결과의 UC 를 구하려면
또 M/R을 돌리기 다양한 부분집합들로 구성될 때 몹시 화가 날것임.
22. - 대용량 INPUT은 하둡에서 Map작업으로 요청 (리듀스 안씀)
- 메모리 서버는 별도의 서버로 존재하며 네트워크로 전송
( 성능을 위해 건별 요청을 하지 않고 내부 버퍼를 둬서 전달)
- 서브셋으로 구성하여 스케일아웃한 구성
- 메모리 절약을 위해 대상값은 모두 숫자형으로 전환 (=bitset사용)
24. 메모리를 확장한 서버를 마련하여 구하고.
Set의 구현체를 이용한다면 쉽게 UC를 구할수 있고 부모/자식관계의 UC
도 구하는 비용이 비교적 손쉬움.
Set p = new Set();
Set c1 = new Set();
Set c2 = new Set();
p.addAll(c1);
p.addAll(c2);
p.size();
25.
26. HashSet의 경우 integer타입을 쓴다고 하면 ,
이론상 4바이트로 계산하면 2.5억개 정도 담겨야 하지만,
실제로 테스트해보면 563만개 정도 담을 수 있음
단일 차원으로 보면 충분해 보이지만,
다양한 차원으로 값이 승계되어야 한다면,
모든 상태를 유지해야 하므로 메모리가 매우 많이 필요함.
27. Bitmask 를 이용해 계산함
이론상 4byte면 32개의 표현이 가능함
1024mb에서 5.3억개 수준의 상태가 표현가능함.
단점은, 숫자형만 가능하다는 점.
그리고 메모리의 크기가 개수가 아닌 max값에 영향을 받는 문제가 있음.
‘394762’이라면, hashset에서는 4byte, bitset에서는 49345byte
28. Bitset의 단점을 보완하기 위해
1만건 정도는 HashSet, 그 이상이 넘어가면 BitSet으로 전환하는
Set을 구현 함.
30. 앞의 문제를 해결 하기위해 최근 개발한 구현체
하나의 bitset이 아니라 논리적 블럭단위로 bitset을 사용함.
31. public class SmartWappedBitSet implements Set<Integer> {
private static final int DEFAULT_BLOCK_SIZE = 10000;//bit갯수
private int INIT_BLOCK_SIZE;
private final Map<Integer,BitSet> folder;
public SmartWappedBitSet(final int blockSize) {
this.INIT_BLOCK_SIZE = blockSize;
folder = new HashMap<Integer,BitSet>();
}
public SmartWappedBitSet() {
this(DEFAULT_BLOCK_SIZE);
}
@Override
public boolean add(Integer e) {
final int index = e / INIT_BLOCK_SIZE;
final int value = e % INIT_BLOCK_SIZE;
if (!folder.containsKey(index)) {
folder.put(index, new BitSet());
}
folder.get(index).set(value);
return true;
}
37. - 예상과 다르게, HashSet의 속도가 매우 느림.
- Smartbitset에서는 여러 개의 bitset을 쓰는데, 생성시간도 꽤 소요됨
- 데이터 분포를 본 결과 만건을 넘는 경우가 대부분이었음
- Hashset에서 bitset전환은 loop로 돌아야 해서 비용이 싸지 않음
38.
39.
40. - 기존대비 1/3 정도 메모리 절약
- 실행속도 3배 상승
- 성능저하는 loop, GC, 잦은 instance가 문제임
수학에서, 기수(基數, 영어: cardinal number)는 수의 일종으로 집합의 크기를 나타내기 위해 사용된다.
여기에서 크기는 간단히 말해 포함된 원소의 수를 뜻하며, 집합론의 용어로는 농도라고 한다
3이 중복되었으므로 3개임.
기본적으로 sorting후 중복제거하는 방법,
Set은 구현체에 따라 HashSet, TreeSet 같은게 존재함. HashSet은 O(1)임.
아까말했듯이 미리 구해놓은 값은 소용이 없음,
요소의 Set을 유지해야 하기 때문에 스케일 아웃한 구성이 필요함.
하둡 M/R로는 UC에 적당하지 않음.
하둡은 KEY단위로 모아서 iterator<Value> 형태로 모아줌.
즉, KEY단위로 묶지만, VALUE에서는 중복체크를 위해 Set을 사용하고
문자열에 구분자를 추가해서 늘려가는 식으로 element를 유지할수밖에없음.
reduce에서 value의 uc를 처리하기위해 내부적인 자료구조를 메모리에 로딩하는것이 필요함.
아니면 Key를 이용해 grouping 할수 있지만, 그러면 KEY를 다시 카운팅하는 작업이 필요함.
그리고 트리구조의 UC를 구하기위해서는 map단계에서 데이터를 늘려주는 구조여야함.
아까말했듯이 미리 구해놓은 값은 소용이 없음,
요소의 Set을 유지해야 하기 때문에 스케일 아웃한 구성이 필요함.
하지만, 데이터를 로딩하고 파싱하고 병렬 프로세싱을 하기위해서는
하둡을 사용하는것이 용이함.
그래서 map/reduce작업을 사용하지 않고
로그파싱과 요청은 map작업만 사용하여 요청함.
실제 UC를 구하는것은 메모리서버를 구현하 개발함.
부족하지만, Bitmap과 같은 bitset을 쓴다면 훨씬 많은 수를 담을수 있음.5.3억개수준.
하지만 bitset은 갯수가 아니라 value에 따라 메모리사용량이 달라짐.
그래서 갯수가 적을땐 hashset, 많을땐 bitset을 쓰도록 함.
536870910 라는 값 1건이 오면... 1G의 메모리할당이 필요함.
536870910 라는 값 1건이 오면... 1G의 메모리할당이 필요함.
536870910 라는 값 1건이 오면... 1G의 메모리할당이 필요함.
536870910 라는 값 1건이 오면... 1G의 메모리할당이 필요함.
bitset대비해서 성능은 버킷사이즈마다 다르지만
1~5억 사이의 숫자를 램덤하게 돌려 약 3.7억개수준의 uc가 나올때
수준임.
메모리는 반정도 적게 쓰고, 실행속도는 반정도 느려짐
기존 hybridset에서 bitset을 smartbitset으로 대체.
더 느려지고 더 CPU를 많이 사용.
(기존방식은 23G정도 변경했더니 38G정도 cpu도 많이씀)
hashset의 bitset(or smartbitset)생성비용과
전환비용이 컸음.
그래서 hybridset에서 아예 대체.