서버 개발 33

DB 절차적 사고 VS 집합적 사고

절차적으로 개발하면 하나 하나에 대한 처리를 던지므로 옵티마이저는 최적화 할 것이 거의 없습니다. (노가다만 하는 거죠) 조회 후 업데이트 또는 입력 select.Execute() while (select.Fetch()) { if(조건?) { update테이블.Execute(); } else { insert테이블.Execute(); } } merge 테이블 using (select ...) on ( 조건 ) when matched then update ... when not matched then insert ... 아이템 강화의 예 for(재료 아이템 종류) { if(아이템이 0개인가?) { delete아이템.Execute(); } else { update아이템수.Execute(); } } update..

DB 테이블 클러스터링 팩터

원하는 정보를 얻기 위해 얼마나 모여 있느냐가 '클러스터링 팩터'입니다. 잘 모여 있을 수록 디스크 IO 효율이 높아져서 성능 또한 좋습니다. 예를 들어, 6건을 얻어 오는데 피지컬 블럭을 2개를 엑세스해서 얻어왔고 3건을 얻기 위해 피지컬 블럭 3개를 엑세스해서 얻어 온다면 6건을 읽는 것이 더 빠릅니다. Index 구조 랜덤 엑세스, 싱글 블럭 IO Clustering Table(Clustered index) 랜던 엑세스를 줄일 수 있으며 멀티 블럭 IO를 할 수 있어서 검색이 빠릅니다. 지정된 컬럼값의 순서대로 로우를 저장시키는 방법 엑세스기법이 아니라 엑세스 효율향상을 위한 물리적 저장기법 검색의 효율을 높여주나 입력, 수정, 삭제시는 부하 증가 분포도가 넓을 수록 오히려 유리 Sorting Ta..

Nested Loop/Sort Merge/Hash Join

다음의 SQL로 두 테이블을 Join합니다. SELECT a.FLD1, ..., b.FLD1,... FROM TAB1 a, TAB2 b WHERE a.KEY1 = b.KEY2 AND a.FLD1 = 'AB' AND b.FLD2 = '10' 1. Nested Loop Join : 어느 한쪽을 드라입밍 해서 조인하는 방식 : 실행 계획의 아이콘입니다. 중첩 루프 즉, for 루프 두 개를 연상하게 합니다. 순차적 ( 부분범위처리 가능 ) 종속적 ( 먼저 처리되는 테이블의 처리범위에 따라 처리량 결정 ) 먼저 처리되는 테이블의 범위가 넓다면 더 많은 처리량이 생기는 거죠. 랜덤 액세스 위주 연결고리 상태에 따라 영향이 큼(key2 = key1) 주로 좁은 범위 처리 에 유리 2. Sort Merge Join ..

DB 옵티마이저

옵티마이져의 목표? SQL로 요구된 결과를 최소의 비용으로 처리할 수 있는 처리 경로를 결정한다. SQL과 옵티마이저 SQL은 처리 절차를 기술하는 것이 아니라, 결과에 대한 요구일 뿐입니다. 처리 절차는 옵티마이저가 생성합니다. 즉 진정한 프로그래머는 옵티마이저입니다. 없는 처리 방법을 생성해주는 것이아니라, 이미 존재하는 처리 방법을 단지 찾아줄 뿐입니다. 사용자가 부여한 영향 요소에 따라 논리적으로 존재하는 처리 방법이 달라집니다. (결국, 책임은 사용자에게 있습니다.) 동일한 결과를 얻을 수 있는 경로는 많으나 효율성의 차이는 큽니다. 옵티마이저는 절대 전지전능하지 않습니다. : 그래서 우리의 역할이 필요 합니다. 옵티마이져에 영향을 미치는 요소 SQL의 형태에 따라 인덱스 클러스터링 연산자의 형..

인덱스의 제대 사용하자

인덱스를 사용하지 않는 경우 index 컬럼의 변경 select userno, name from [user] where SUBSTRING(name, 1, 7) = 'user123' Not operator select userno, name from [user] where name 'abc' null, not null select userno, name from [user] where name is not null 옵티마이저의 취사선택 SQL 작성 규칙 좌변을 가공하지 마라 where SUBSTRING(name, 1, 3) = 'abc' → where name like 'abc%' where sal * 12 = 2000 → where sal = 2000 / 12 where isnull(cost, 0) < ..

부분범위 처리와 전체 범위처리

user 테이블이 있는데 1000만건입니다. select * from [user] 를 실행하면 언제 부터 결과를 받을 수 있나요? 읽는 데이터 모두가 답입니다. 데이터베이스는 운반 단위에 차면 바로 바로 응답합니다. 그래서 0.0001초 만에 결과를 받기 시작합니다. 이 것이 바로 부분 범위 처리 입니다. select * from [user] order by name를 실행하면 언제 부터 결과를 받을 수 있나요? 이것은 전체를 읽어서 name로 소트를 해야만 결과를 받을 수 있습니다. 이 것이 바로 전체 범위 처리입니다. 전체 범위 처리 : 풀 스캔 후 가공하여 Array Size(운반 단위) 만큼 추출되어야 결과를 얻음 부분 범위 처리 : 조건을 만족하는 Row 수가 Array Size에 도달되면 결과..

아크 모델(exclusive or)에서의 주의점

다음과 같은 모델을 아크라고 하며 exclusive or 관계 입니다. select A.missionno, case A.owner_flag when 1 then B.name when 2 then C.guildname end name from missions A, [user] B, guild C where A.quest_id = 1 and ((A.owner_flag = 1 and A.userno = B.userno) or (A.owner_flag = 2 and A.guildno = C.guildno)) 이 SQL을 실행하니 희안하게도 같은 이름이 복사가 되어 보여 집니다. 옆사람에게 물으니, "에이~ 이런 것도 모르세요? distinct 있자나요~" 그래서 신기하게도 distinct 하나만 붙여주니 원하는..

리커시브 모델의 활용

부서 코드 테이블을 다음과 같이 계층형으로 표현합니다. 부서 ID가 다음과 같이 입력되어 있습니다. 1120이 테라PC실이인데 상위 조직이 1100이 아니라 1200으로 바뀌게 되면 1120이 1220으로 변경되어야 합니다. 그런데 이것만 바꾸는 것이 아니라 아래 모든 자식들도 바꾸어 주어야 합니다. 부서 코드 테이블 뿐만 아니라 관계된 테이블이 있다면 모두 다 업데이트 해야 합니다. 사원에 부서 코드가 있었다면 관계 있는 모든 사원의 부서 코드가 업데이트 되어야 합니다. 이는 부서 코드 테이블에 상위 부서 컬럼이 추가 되면 해결됩니다. 상위 부서로서 '리커시브 모델'로 표현한 것입니다. 리커시브로 설계 했을 뿐인데 상위 조직이 바뀌면 상위 부서 ID 하나만 수정하면 됩니다. Happy!!!

테이블 조인 하면 느리다?

다음의 1번과 2번 중 어느쪽이 더 빠를까요? 1. Join이 빠르다. select A.userno, A.name, B.guildname from [user] A JOIN guild B ON A.guildno = B.guildno 2. Join하지 않는 것이 빠르다. select userno, name, guildname from [user] 1번이 더 빠릅니다. 디스크 IO 보다 CPU와 메모리가 훨씬 빠르기 때문입니다. 퍼포먼스에 가장 큰 영향을 주는 것이 디스크 IO 입니다. 그럼 디스크 IO량이 어떻게 되는지 따져봅시다. 1번은 108 * 100 바이트(약 1만)+ 32 * 10만 바이트(약 320만) = 약 321만 바이트 2번은 132 * 10만 바이트(약 1320만) 바이트 = 약 1320만..

옵티마이저 맛보기

우리는 데이터베이스에게 SQL Query를 통해 문제를 내고 데이터베이스는 옵티마이저는 최선을 다해 그 결과를 가져옵니다. 이 옵티마이저는 우리가 생각하는 이상으로 아주 뛰어난 녀석입니다. Nested loop join을 한다면 여러분이 옵티마이저라면 guild와 user 두 테이블중 어떤 테이블을 먼저 드리아빙 하겠습니까? user 테이블을 읽고 guild테이블을 읽음 반대로 guild 테이블 읽고 user 테이블을 읽음 select B.guildname, A.userno, A.name from [user] A, guild B where A.guildno = B.guildno Nested loop join : 어느 한 쪽 테이블을 먼저 드라이빙해서 조인하는 방식입니다. select B.guildname..