출처 : http://www.webmadang.net/database/database.do?action=read&boardid=4001&page=null&seq=5

[MSSQL - GROUP BY HAVING 을 이용한 중복 데이타 체크]



1 - 단일 테이블에서 GROUP BY HAVING 을 이용한 중복 데이타 체크

아래와 같은 로그인 정보를 기록하는 9개의 레코드를 가진 테이블이 있다고 가정하겠습니다. 테이블의 이름은
"loginLog_tbl" 이고 로그인 로그(log)를 기록해야 하니 당연히 중복된 데이타가 들어가 있을것입니다. 

위 테이블의 레코드를 보면 mfcchang이라는 uid가 3회나 로그인 했다는 것을 알 수 있습니다. 레코드의 갯수가 작아서
눈으로도 파악이 되지만 레코드의 갯수가 많을때는 다음과 같은 쿼리문으로 간편하게 파악 할 수도 있습니다.

SELECT uid, count(*) AS loginCount FROM loginLog_tbl GROUP BY uid ORDER BY loginCount DESC

위와 같은 쿼리를 실행해보면 GROUP BY 에 의해서 uid 컬럼의 count가 집계되고 결과는 아래와 같습니다.

 

여기에 Having 절의 제약조건을 이용해서 loginCount가 1 보다 큰것만 출력해 보겠습니다. loginCount 는 count(*)의 엘리어스 이니까, Having 절 이하는 아래와 같을 것입니다.

SELECT uid, count(*) AS loginCount FROM loginLog_tbl GROUP BY uid HAVING count(*) > 1

출력해 보면 결과는 아래와 같습니다. 아래의 결과에서 두번 즉 2회 이상 로그인한 사람은 kimchi 와 mfcchang 이라는 uid의 소유자 뿐임을 알수 있습니다.

 

어떠한 경우에서든 데이타의 중복을 확인하고자 한하면 바로 위의 쿼리문을 이용하시면 됩니다. 중복을 체크하고자 하는 
기준이 되는 컬럼만 바꾸면 될 것입니다.



2 - 두개 이상의 테이블에서 GROUP BY HAVING 을 이용한 중복 데이타 체크 

그렇다면 중복을 체크하고자 하는 컬럼이 위와 같이 테이블이 하나가 아니고 둘또는 셋이상에 걸쳐서 존재한다면 어떻게
처리하면 될까요? 테이블간에 합집합의 결과를 모두 보여주는 UNION ALL 로 테이블을 결합하시면 됩니다.

아래와 같이 로그인 정보를 기록하는 테이블이 하나 더 있고, 이 테이블은 예전에 퇴사한 선임자가 만들어 놓은 것이라고 
가정하겠습니다. 테이블의 이름은 loginLogTABLE 입니다.

 

처음에 사용했던 loginLog_tbl과 바로 위의 logLogTABLE에서 uid 컬럼의 데이타값이 2 개 이상인 것을 찾아내는
쿼리는 아래와 같습니다.

SELECT uid, count(*) AS loginCount FROM 
SELECT uid FROM loginLog_tbl UNION ALL SELECT uid FROM loginLogTABLE ) AS T
GROUP BY uid HAVING count(*) > 1

하나의 테이블을 사용할때와 틀린부분은 UNION ALL 로 해당 테이블을 묶어서 서브쿼리로 처리한다는 것뿐입니다.
결과는 아래와 같습니다. 두개의 테이블의 레코드 갯수가 몇개 없으니 눈으로도 확인 가능할 것입니다.

작성자: 다자래(mfcchang@naver.com) 
웹제작 토탈 커뮤니티 http://www.webmadang.net


출처 : http://sunjinyang.wordpress.com/2009/06/18/debugging-memory-leaks-with-tcmalloc-google-perftools/


리눅스에서 메모리 침범이나 메모리 누수, 혹은 복잡한 메모리 접근 관련 오류를 디버깅할때는 대부분 Valgrind 도구를 이용합니다. 하지만 Valgrind는 많은 메모리를 사용하고 실행 속도가 현저하게 느려지기 때문에, 별도의 타겟 장비에서 제한된 조건으로 동작하는 어플리케이션에는 조금 무리가 있습니다. 게다가 Valgrind의 메모리 검사 도구는 프로그램이 종료된 시점에서 누수된 메모리만 찾기 때문에, 실행 중에는 엄청나게 메모리를 사용하다가 정상적인 객체 해제 루틴이 호출되면 모든 메모리가 정리되어 찾을 수 없는 경우는 발견하지 못합니다.

구글 성능 도구를 다시 검토하고 사용하게 된 이유도 바로 여기에 있습니다. 현재 디버깅 중인 프로그램의 문제가 대략 이렇습니다. 몇날 며칠이고 문제없이 가동해야 하는 프로그램이 특정 설정을 적용한 후에는, 자고 일어나면 10~20메가씩 메모리 점유율이 한꺼번에 올라갑니다. 하지만 Valgrind 도구를 사용해도 어느 부분이 문제인지 찾을 수가 없습니다. 지난 글에서 TCMalloc 메모리 할당자로 교체한 후 문제가 해결된 줄 알았던 바로 그 패턴이기도 합니다. 그래서 이번에는 프로파일 기능을 이용해 직접 메모리 누수를 디버깅 해보고, 나중을 위해 그 과정을 정리해 보았습니다.

디버깅 환경

디버깅 환경은 우분투 9.04 x86_32 플랫폼입니다. x86_64 플랫폼에서는 이상하게 호출 그래프가 그려지지 않아서 일단 무시했습니다. 사용한 버전은 공식 홈페이지에서 다운로드 받은 1.2 버전입니다. 1.3 버전은 이상하게 프로파일 기능이 동작하지 않아 역시 무시했습니다.

TCMalloc 도구 설치 및 연결

호출 그래프를 생성하기 위해 dot 프로그램이 필요한데 이 프로그램은 graphviz 패키지에 들어있으므로 설치해야 합니다.

$ sudo apt-get install graphviz

우선, 공식 홈페이지에서 google-perftools 압축 파일을 다운로드 한 뒤 다음과 같이 빌드하고 설치합니다. [2011.05.02 추가]INSTALL 문서에도 명시되어 있듯이, x86_64 환경에서는 libunwind 라이브러리를 미리 설치한 뒤 빌드해야 정상적으로 동작합니다.

$ cd google-perftools*
$ ./configure --prefix=/usr
$ make
$ sudo make install

TCMalloc 라이브러리를 연결하는 방법은 공식 문서에도 나와 있듯이 디버깅할 프로그램 링크 마지막에 ‘-ltcmalloc‘ 옵션을 추가하거나, 실행할때 프로그램 앞에 ‘LD_PRELOAD=/usr/lib/libtcmalloc.so execute-file‘ 처럼 라이브러리를 먼저 로드해주면 됩니다. 저는 첫번째 방법을 사용했습니다. [2011.05.02 갱신] 언제부터인지는 확실치 않지만 첫번째 방법은 동작하지 않고 두번째 방법으로 해야 메모리 프로파일이 정상적으로 동작합니다.

참고로, 디버깅할 프로그램을 컴파일할때는 디버깅 심볼 옵션(-g)이 있어야 호출 그래프에서 정확한 함수 이름이 표시됩니다. 또한 최적화 옵션(-O2 등)을 사용 안하면 더 정확한 함수 호출 그래프를 얻을 수 있습니다.

프로파일 데이터 얻기

TCMalloc 라이브러리를 연결해도 기본적으로 프로파일 기능은 동작하지 않습니다. HEAPPROFILE 환경변수에 프로파일 정보를 주기적으로 덤프할 파일 이름 접두사(prefix)를 지정해야만 동작합니다.

$ HEAPPROFILE=/tmp/profile execute-file

접두사는 파일 절대 경로로 디렉토리를 포함할 수 있습니다.

만일 덤프 파일이 너무 자주 생성되거나 반대로 너무 드물게 생성된다면 환경 변수를 통해 간격을 조절할 수 있습니다.

$ HEAPPROFILE=/tmp/profile 
  HEAP_PROFILE_ALLOCATION_INTERVAL=107374182400 
  execute-file

더 자세한 옵션은 공식 문서를 확인해 보시기 바랍니다.

위 예제에서 지정한 방식대로 프로그램을 실행하면 /tmp/profile.0001.heap/tmp/profile.0002.heap/tmp/profile.0003.heap 등과 같은 프로파일 덤프 파일이 실행 도중 계속 생성됩니다.

결과 그래프 얻기

포스트스크립트(PostScript) 파일 형식으로 메모리 프로파일 정보를 포함한 함수 호출 그래프를 얻으려면 다음과 같이 형식으로 pprof 프로그램을 실행하면 됩니다.

$ pprof --ps --lines 
    execute-file 
    /tmp/profile.0001.heap 
    > profile-0001.ps

프로파일 덤프 파일에 대하여 하나씩 그래프를 생성해 직접 눈과 손으로 비교하는 것도 나쁘지 않지만, 두 프로파일의 차이점만 그래프로 만들어주는 옵션이 있으므로 이를 사용하면 더 편리합니다. 즉, 시간대별 메모리 사용량의 달라진 부분이 정확하게 어느 함수 호출 때문인지 알 수 있게 해줍니다.

$ pprof --ps --lines 
    --base /tmp/profile.0001.heap 
    execute-file 
    /tmp/profile.0002.heap 
    > profile-0002-diff.ps

물론, PDF(--pdf), GIF(--gif) 등과 같은 다른 형식으로 그래프 파일을 얻을 수도 있습니다. 더 자세한 옵션은 ‘pprof --help‘를 참고하시면 됩니다.

결론

며칠간 디버깅에 적용해보니 문제가 발생한 패턴이 무엇이었는지도 찾아내고, 간과했던 작은 메모리 누수 버그들도 함께 발견할 수 있었습니다. 하지만, 언제나 그렇듯이, 디버깅 사태까지 오기 전에 더 튼튼하게 설계하고, 더 꼼꼼하게 프로그래밍하고, 더 철저하게 코드 리뷰와 테스트를 거치는 게 정도임을 새삼 깨닫습니다.

출처 : http://blog.daum.net/jchern/13756799


download : http://code.google.com/p/google-perftools/downloads/list

toturial : http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html

 

설치방법

tar -zxvf google-perftools-1.6.tar.gz

cd google-perftools-1.6

./configure

make

su

make install

 

 

사전 작업

1. 프로파일링을 워하는 프로그램 컴파일시에 -lprofiler를 같이 컴파일한다.

2. <google/profiler.h>를 include한다

 

bash >

export LD_LIBRARY_PATH=/usr/local/lib

export CPUPROFILE=output.txt( CPUPROFILE로 설정된 파일명으로 출력파일이 생성된다 )

 

특정 함수에 대해서만 프로파일링을 하기 위해서는

ProfilerStart()와 ProfilerStop()를 사용하면 된다.

ProfilerStart()에는 함수명을 파라미터로 준다.( ProfileStart("test_func"); )

여기까지 설정한후에 실행을 하면

CPUPROFILE에 설정한 파일명으로 파일이 하나 생성이 된다.

이파일은 바이너리 포맷이라서 그냥 볼수는 없고

 

/usr/local/bin/pprof 라는 파일로 볼수 있다.

/usr/local/bin/pprof [실행파일명] [output.txt]

(pprof)라고 프로프트가 뜨면 top를 입력

 

(pprof) top

 

상위에 노출되는 함수들이 실행시간이 오래걸리는 함수들이다.

 

 

 

특정 함수에 대한 프로파일링 :

pprof    --gv --focus=함수명   실행파일 출력파일

 

특정 함수를 제외한 프로파일링

pprof   --gv --ignore=함수명  실행파일 출력파일


 

좀더 자세한 내용은 요기서 ; http://google-perftools.googlecode.com/svn/trunk/doc/cpuprofile.html

 

  1. iostat
  2. 별도의 설치 필요없음, 물리적 드라이버 별로 기본적인 Disk Read/Write 볼 수 있음
  3. 한 개 이상의 디스크 드라이브에 대한 입출력 통계와 CPU 활용량

    arg-cpu
    %user
    %nice
    %system
    %iowait
    %steal
    %idle
    마지막 재부팅 이후의 평균 CPU 활용량 어플리케이션 등 사용자 모드에 소모된 시간 nice를 사용하여 스케줄링 우선순위가 바뀐 프로세스에 소모된 시간 시스템(커널)이 사용한 시간 디스크I/O 요청 때문에 CPU가 대기한 시간 다른 가상 CPU가 서비스하는 동안 비자발적으로 대기한 시간 대기한 시간
    Device
    tps
    kB_read/s
    kB_wrtn/s
    kB_read
    kB_wrtn
    디바이스 구분 초당 전송(입출력) 수 초당 읽혀진 KB (Blk일 경우 512바이트 블록수) 초당 쓰여진 KB (Blk일 경우 512바이트 블록수) 지금까지 읽혀진 KB(Blk일 경우 512바이트 블록수) 지금까지 쓰여진 KB(Blk일 경우 512바이트 블록수)
  4. vmstat
  5. 별도의 설치 필요없음, 시스템의 리소스 상황(CPU, I/O, Memory)을 모니터링 할 수 있음 (http://jikime.tistory.com/286)

  6. vmstat(옵션없음) - 마지막 부팅 이후의 평균값

  7. vmstat 2 10 => 2초 간격으로 10회 정보 갱신

    procs memory swap io system cpu
    r b w swpd free buff cache si so bi bo in cs us sy id wa
    현재 실행중인 프로세스의 수(CPU 접근 대기 중인 실행 가능 프로세스 수) 인터럽트가 불가능한 sleep 상태에 있는 프로세스의 수 (I/O 처리를 하는 동안 블럭 처리된 프로세스) 강제로 스왑아웃된 프로세스 사용하고 있는 swap 메모리 양(사용된 가상 메모리 용량) 사용가능한 메모리 양 버퍼로 사용되고 있는 메모리 양 캐시로 사용되고 있는 메모리 양 swap in(디스크에서 메모리로 스왑된 메모리 용량) swap out(디스크로 스왑되어 나간 메모리 용량) 초당 블럭 디바이스로 보내는 블럭 수(블록 장치로 보내진 블록) 초당 블럭 디바이스로부터 받은 블럭 수(블록 장치에서 받아온 블록) 초당 인터럽트 되는 양 초당 context switch되는 양 사용자의 CPU 사용 시간 비율(CPU가 사용자 수준 코드를 실행한 시간, 백분율 단위) 시스템의 CPU 사용 시간 비율(CPU가 시스템 수준 코드를 실행한 시간, 백분율 단위) CPU idle time(백분율 단위) 입출력 대기
    1. top
    2. 별도의 설치 필요없음, CPU 점유 프로세스들을 실시간으로 조회하는 명령어 (http://weezzle.net/1360)

    • 1줄 top : 시스템의 전반적 상태(가동시간 등)

    • 2줄 Tasks : 프로세스들의 상황

    • 3줄 CPU : CPU의 상황

    • 4줄 Mem : 메모리 상황

    • 5줄 Swap : 스왑 메모리 상황

    • 6줄

      PID
      USER
      PR
      NI
      VIRT
      RES
      SHR
      S
      %CPU
      %MEM
      TIME+
      COMMAND
      프로세스 ID 프로세스를 실행시킨 사용자 ID 프로세스의 우선순위 NICE 값 가상 메모리의 사용량(SWAP+RES) 현재 페이지가 상주하고 있는 크기(Resident Size) 분할된 페이지, 프로세스에 의해 사용된 메모리를 나눈 메모리의 총합 프로세스의 상태(Sleeping, Running, sWapped out process, Zombies) 프로세스가 사용하는 CPU의 사용율 프로세스가 사용하는 메모리의 사용율 CPU TIME, hundredths 실행된 명령어
    1. free
    2. 시스템의 실제메모리와 스왑메모리에 대한 사용현황을 확인할 수 있는 명령어 (http://blog.naver.com/PostView.nhn?blogId=jwmoon74&logNo=100174011942)
    • 1줄 Mem : 시스템의 물리적인 메모리에 대한 사용량을 각 필드 단위로 표시

      total
      used
      free
      shared
      buffers
      cached
      전체 메모리의 용량으 Kbyte단위(default)로 표시 현재 시스템에서 사용중인 메모리의 량을 Kbyte 단위로 표시 현재 시스템에서 사용중이지 않은 메모리의 량을 Kbyte단위로 표시 현재 시스템에서 공유한 메모리의 용량을 표시 현재 시스템에서 buffering된 메모리의 량을 표시 현재 시스템에서 caching된 ㅣ메모리의 량을 표시
    • 2줄 -/+ buffers/cache : 현재 캐시 메모리에서 버퍼링된 사용량을 표시(used/free)
    • 3줄 Swap : 서버설치 시에 결정한 스왑메모리의 량, 스왑메모리는 디스크의 일부분을 메모리로 잡아서 설정되기 때문에 스왑메모리가 많이 사용되고 있다는 것은 시스템의 전체적인 속도가 떨어진다는 것을 의미하며 지속적으로 스왑메모리가 사용된다는 것은 결국 실제 메모리를 증설해야 한다는 것이다.

      total
      used
      free
      시스템의 전체 스왑메모리의 량을 표시 전체 스왑메모리 중에서 현재 사용중인 스왑메모리의 량을 표시 전체 스왑메모리중에서 사용되지 않고 남아 있는 메모리의 량
    1. iotop
      1. 별도의 설치 필요함, Python 2.5+, linux kernel 2.6.20+ 이 2개의 프로그램이 기본적으로 설치되어 있어야 함
      TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND

     

     


    CPU - perf, top, htop

    Memory - valgrind, smem

    Disk I/O - nmon, bonnie, sysstat

    Network - netperf, iftop, netstat

     

     

    출처 : http://visu4l.tistory.com/398

    COPY & PASTE 로 간편하게 사용할 수 있는 SQL Server Trobleshooting 에 필요한 쿼리들을 정리하려고 합니다. 다소 심플하며 성의없어(?) 보이는 포스팅이 이어질지 모르겠습니다만 이 모든 것이 이~편한 세상을 위한 것임으로 ... ㅋㅋㅋ 

     

     

    sys.dm_exec_requests

     

    SQL Server 내에서 실행 중인 각 요청에 대해 현재 처리 상태를 확인합니다. 예를 들어, 대용량 DB CHECKDB 하면서 소요 예상 시간이 궁금할 , 현재 쿼리 요청에 대한 작업 상태를 확인할 , 유용하게 적용할 있습니다. 

     

    아래 예제는 Session ID 51에 대한 진행되는 명령어, 실행 상태, 진행 작업의 백분율을 확인할 수 있습니다.

    이 때, Session ID 51에서는 DBCC CHECKDB 를 수행하고 있는 상태입니다.

    SELECT session_id, command, status, percent_complete FROM sys.dm_exec_requests 

    WHERE session_id = '51';

     

     

    [실행결과]

     

    session_id     command                    status                percent_complete

    ----------------------------------------------------------------------------------------------------------

    51               DBCC TABLE CHECK      runnable            84.04607

    (1개 행 적용됨)

     

     

    [참고자료]

    sys.dm_exec_requests

    http://technet.microsoft.com/ko-kr/library/ms177648(SQL.90).aspx

     

    원본 위치 <http://laigo.kr/111

    + Recent posts