« Previous : 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : Next »
길다란 복합 인덱스가 능사가 아니다?


작성: 박노철(maceo.park@gmail.com)


오늘 기존 테이블에 대한 index tuning 을 하다가 발견한 현상.

테이블 T1 사이즈 : 1500만건
T1에는 클러스터드 인덱스가 있다고 가정하자.

select * from T1 where a = 1 and b = 1 and c = 1 and d = 1

이라는 쿼리가 있다고 치자. 이럴때는 보통

create index idx__a_b_c_d on T1 (a,b,c,d)

이렇게 잡는다.

그런데 다음 쿼리가 들어왔다.

select * from T1 where c = 1 and d = 1

그러면 c,d 에
create index idx__c_d on T1 (c,d)

복합인덱스를 잡으면 된다.

이제 우리는 a,b,c,d 와 c,d 에 대한 인덱스 두개를 가지고 있다. 일반적으로 위와 같이 해결 하지만 다른 방법도 생각해볼 수 있다. where조건을 구성하는 컬럼을 분해해서 다음과 같이 인덱스를 구성하는 것이다.

create index idx__a_b on T1 (a,b)
create index idx__c_d on T1 (c,d)

좀 이상하지 않은가?????

이렇게 하면 where a=1 & b=1 & c=1 & d=1 에 대해서 idx__a_b를 타게 될테니 idx__a_b_c_d가 있을 때보다 읽기수가 대폭 증가할 것이라고 예상이 된다. idx__a_b를 탄 후에 bookmark lookup 을 해서 c,d를 체크해야 할 테니. 하지만 이런 경우 SQL Server는 똑똑하게 동작한다. 옵티마이저는 bookmark lookup 의 비용이 과도하다고 판단하면 T1의 두개의 인덱스 idx__a_b와 idx__c_d를 동시에 Index Seek을 해서 join 을 해버린다. maxdop 가 높고 시스템 가용자원이 남아서 병렬 계획을 수립할 가능성이 높으면 더더욱 두개의 인덱스를 병렬로 seek하는 방향으로 실행계획이 유도된다. join 할 때는 각각의 인덱스 끝에 붙어 있는 클러스터드 인덱스 키를 이용하는 것 같다. a,b의 선택성이 좋아서 bookmark lookup 비용이 과도하지 않으면 저렇게 동작하지 않는 것 같다.

인덱스를 위와 같이 잡을 때의 이점은 명백하다. c,d 컬럼에 대해서 중복 인덱스를 잡을 필요가 없어진다. 그렇다고 해서 idx__a_b_c_d가 있을 때보다 읽기수가 엄청나게 증가하는 것은 아니다. 물론 늘어나긴 하지만 감당할만한 수준이다.


결론: 액세스가 빈번하지는 않으나 테이블 사이즈가 매우 커서 공간을 절약할 필요가 있는 경우 where조건을 구성하는 컬럼을 분해해서 각각의 index를 잡는 전략을 고려해볼 수 있다.

Posted by maceo

09 28, 2006 17:36 09 28, 2006 17:36
, ,
Response
No Trackback , a comment
RSS :
http://merritt.co.kr/tt/rss/response/73

대상 테이블 1500만건. 데이터 사이즈 6.6G
작업 : 클러스터드 인덱스 생성작업
maxdop 2 일 때 걸린 시간 : 3분 4초
maxdop 4 일 때 걸린 시간 : 2분 17초
maxdop 16 일 때 걸린 시간 : 4분 28초
maxdop 32 일 때 걸린 시간 : 12분 30초

maxdop 가 커지면 스레드들끼리 gather stream 작업을 하는데 SQL Server 2000은
그 부분에서 매우 비효율적인 것 같다. 2005 에서는 얼마나 좋아졌으려나....

Posted by maceo

09 28, 2006 12:04 09 28, 2006 12:04
, , ,
Response
A trackback , a comment
RSS :
http://merritt.co.kr/tt/rss/response/72

파티션 테이블, 병렬계획 & 성능 고려사항들

http://blogs.msdn.com/sqlcat/archive/2005/11/30/498415.aspx
번역:박노철(maceo.park@gmail.com)

Q:SS2005 의 파티션 테이블에 쿼리를 날릴 때 어떤 종류의 병렬 계획이 나올 것이며 성능에는 어떤 영향을 미치는가?

A:먼저 파티셔닝에 대한 간략한 배경을 소개하겠다. SS2005의 테이블 파티셔닝은 관리와 가용성 측면에서 많은 향상을 가져왔다. 관리적 측면에서 보자면, 데이터 파티션에 대해서 메타데이터 스위치 인, 아웃을 가능케 했다(sliding window requirements를 지원한다. (뭔소리여? -_-)) 가용성 측면에는 온라인 인덱스 리빌드, 병렬 실행, 파일그룹의 piecemeal 리스토어가 가능하다.

이제 파티션 테이블이 성능에 어떤 영향을 미치는지 살펴보자. 파티셔닝을 사용하는지 아닌지에 관계없이 병렬 계획 선택여부는 CPU갯수, 쿼리 비용, 가용 메모리와 현재 workload 에 의해서 결정된다. 이 글에서 이야기하는 모든 것들은 병렬 계획이 가능할때만 유효한 것들이다.

쿼리가 하나의 파티션을 사용할 때 SS2005는 maxdop에 설정된 수치까지 여러개의 스레드를 사용해서 병렬로 데이터를 읽어올 수 있다. maxdop는 보통 시스템에 설치된 CPU갯수와 같은 값을 의미하는 0으로 설정되어 있다. 쿼리가 두개 이상의 파티션에서 데이터를 읽어올 때 파티션당 단 하나의 스레드만 사용될 수 있다.

만약 파티션 갯수가 maxdop와 같거나 더 적다면 데이터가 한쪽으로 치우침으로 인해서 CXPACKET 대기가 생길 수 있다. 파티션 갯수가 maxdop보다 크면 SS2005는 하나의 스레드가 특정 파티션에서 작업을 끝내면 자동적으로 다음 파티션으로 이동한다. 16개의 파티션을 가지고 있고 maxdop가 8이라면 첫 8개의 스레드는 파티션1-8에 대해서 작동한다. 작업이 끝난 첫번째 스레드는 파티션9에서 돌게 된다.

만약 8개 이상 CPU를 가진 기계라면, 최악의 경우는 두개의 파티션에 걸쳐있는 단일 SELECT문이다. (테이블1 참조) 테이블2에 노란색 강조 부분, 파티션 80,81과 Executes 컬럼의 스레드 숫자를 보면, 노란색 부분 이후의 단계에서 maxdop가 적용될 수 있음에도 불구하고 데이터를 읽어올 때는 파티션당 하나의 스레드만 돌아간다. (녹색 강조 참고)

Table 1: Retrieve 2 weeks of data

SELECT   

      SUM(Sales_Qty) as Sales_Qty,

      SUM(Sale_Amt)  as Sales_Amount

FROM   SalesDB.dbo.Tbl_Fact_ Sales – Partitioned by week

WHERE  date_id between '20050703' and '20050716'

Table 2: Set Statistics Profile:  MAXDOP = 12

Rows

Executes

StmtText

1

1

SELECT SUM([Sales_Qty]) [Sales_Qty],SUM([Sale_Amt]) [Sales_Amount] FROM [SalesDB].[dbo].[Tbl_Fact_Sales] WHERE [date_id]>=@1 AND [date_id]<=@2

0

0

  |--Compute Scalar(DEFINE:([Expr1002]=CASE WHEN [globalagg1008]=(0) THEN NULL ELSE [globalagg1010] END, [Expr1003]=CASE WHEN [globalagg1012]=(0) THEN NULL ELSE [globalagg1014] END))

1

1

      |--Stream Aggregate(DEFINE:([globalagg1008]=SUM([partialagg1007]), [globalagg1010]=SUM([partialagg1009]), [globalagg1012]=SUM([partialagg1011]), [globalagg1014]=SUM([partialagg1013])))

2

1

           |--Parallelism(Gather Streams)

2

12

                |--Stream Aggregate(DEFINE:([partialagg1007]=COUNT_BIG([SalesDB].[dbo].[Tbl_Fact_Sales].[Sales_Qty] as [ss].[Sales_Qty]), [partialagg1009]=SUM([SalesDB].[dbo].[Tbl_Fact_Sales].[Sales_Qty] as [ss].[Sales_Qty]), [partialagg1011]=COUNT_BIG([SalesDB].[dbo].[Tbl_Fact_Sales].[Sale_Amt] as [ss].[Sale_Amt]), [partialagg1013]=SUM([SalesDB].[dbo].[Tbl_Fact_Sales].[Sale_Amt] as [ss].[Sale_Amt])))

20577235

12

                     |--Nested Loops(Inner Join, OUTER REFERENCES:([PtnIds1006]) PARTITION ID:([PtnIds1006]))

2

12

                          |--Parallelism(Distribute Streams, Demand Partitioning)

2

1

                          |    |--Constant Scan(VALUES:(((80)),((81))))

20577235

2

                          |--Index Seek(OBJECT:([SalesDB].[dbo].[Tbl_Fact_Sales].[IX_Tbl_Fact_Sales_SKDteItmStrIDSalQtySalAmtDiscMkd] AS [ss]), SEEK:([ss].[SK_Date_ID] >= (20050703) AND [ss].[SK_Date_ID] <= (20050716)) ORDERED FORWARD PARTITION ID:([PtnIds1006]))

예를 들어 월단위로 파티션된 테라바이트급 매출 테이블이 있다고 하자. 일반적인 쿼리 패턴이라면, 이달과 전달 또는 이달과 1년전을 비교할 것이다.

Table 3:  MONTHLY Partitions

WHERE clause

Partitions

Retrieval Parallelism

Single SELECT statement

SELECT …. WHERE DateCol BETWEEN ’10/1/2005’ and ‘11/30/2005’

2

1 thread per partition *

SELECT

UNION SELECT

[UNION SELECT]

Select …. Where DateCol between ’10/1/2005’ and ‘10/31/2005

UNION

Select …. Where DateCol between ’11/1/2005’ and ‘11/30/2005

1 per select

MAXDOP per partition

Table 4:  WEEKLY Partitions:  Sales for November 1-15

WHERE clause

Partitions

Retrieval Parallelism

Single SELECT statement

SELECT SUM(Sales) from WKSales

WHERE DateCol BETWEEN ’11/1/2005’ and ‘11/15/2005’

3

1 thread per partition *

SELECT

UNION SELECT

[UNION SELECT]

SELECT SUM(Sales) from WKSales

WHERE DateCol BETWEEN ’11/1/2005’ and ‘11/5/2005’

UNION

SELECT SUM(Sales) from WKSales

WHERE DateCol BETWEEN ’11/6/2005’ and ‘11/12/2005’

UNION

SELECT SUM(Sales) from WKSales

WHERE DateCol BETWEEN ’11/13/2005’ and ‘11/15/2005’

1 per select

MAXDOP per partition

비록 관리나 가용성 측면에서 어려움이 있긴 하지만 거대한 단일 테이블이 성능상 더 좋은 경우도 있다. 예를 들어 1TB 파티션 테이블에 두개의 파티션을 읽어야 하는 쿼리가 있다고 하면, SS2005는 파티션당 1개의 스레드만 할당한다. 하지만 SS2005는 1TB짜리 단일 테이블에 대해서는 maxdop를 적용하여 데이터를 읽어온다.

Table 5:  Monolithic BigSalesTable

WHERE clause

Partitions

Retrieval Parallelism

Single SELECT statement

SELECT …. WHERE DateCol BETWEEN ’10/1/2005’ and ‘11/30/2005’

N/A

MAXDOP

Best Practices:

파티션과 병렬 실행의 퍼포먼스에 관한 위의 커멘트는 DW, 배치 프로세싱, 리포팅에 적용가능하다. 모든 DW가 병렬 쿼리를 허용하지는 않을 것이다. 병렬 계획은 시스템에 실행되는 쿼리가 몇개 없고 실행 시간을 최소화 하기 위해 가능한 많은 리소스를 사용하기를 위할 때 가장 효과적이다. 만약 DW가 이미 동시성이 매우 높은 환경이라면, 병렬 계획은 throughput이나 응답 시간을 향상시켜주지 않을 것이다. 이미 수많은 단일 스레드 쿼리들이 가용 자원을 대부분 소비하고 있을 것이기 때문이다. 최고의 퍼포먼스를 위해서, 동시성이 높은 OLTP시스템에서도 병렬 계획을 원하지는 않을 것이다.

파티셔닝 정밀도(일별, 주별, 월별)를 결정할 때 사용자들의 일반적인 쿼리 패턴을 고려해야 하며 CPU8개 이상의 시스템에서 최고의 성능을 위해서는 최소한 maxdop개의 파티션을 사용하도록 해야 한다. 테이블 3,4에서 보여준바와 같이 SQL문을 여러개의 단일 파티션 쿼리로 재작성해야 최고의 성능을 얻을 수 있다.


Posted by maceo

09 27, 2006 12:22 09 27, 2006 12:22
, ,
Response
No Trackback , a comment
RSS :
http://merritt.co.kr/tt/rss/response/71

SW 아키텍트로 가기 위한 필독서들...

사실 아직 일천한 수준이긴 한데... SW 아키텍트로 가기 위해서는 기본적으로 뭘 봐야할지에 대해서 한번 정리를 하고 싶어졌다. 일단은 개발을 잘해야겠지? 설계도 잘해야겠고. 그런데 개발/설계를 잘 한다함은 특정 플랫폼에 종속되는 것이 아니라 어떤 플랫폼이더라도 통용될 수 있을 정도로 잘해야 한다는 것을 의미한다. 이런 능력을 기르는데 필독서는 다음 두권이다.

GOF의 디자인 패턴  Erich Gamma 외 지음, 김정아 옮김
이 책은 디자인패턴과 보다 효과적인 객체지향 프로그래밍에 관심이 있는 개발자들을 위한다. 책을 읽기위해서는 자바나 C++과 같은 객체지향 언어에 어느정도 익숙해져야 한다. 디자인 패턴 자체가 보다 재사용가능하고 유지보수가 쉬운 객체지향 프로그래밍 구현을 목적으로 하고 있기 때문에 기본적인 이해는 필수적이다.
Refactoring - 기존 코드의 디자인을 개선하는 방법  Martin Fowler 지음, 윤성준.조재박 옮김
리팩토링은 소프트웨어의 외부 기능을 변경하지 않으면서 내부 구조를 바꾸는 기술이다. 리팩토링을 사용하면 나쁜 디자인의 코드를 취해서, 외부 기능을 변경하지 않고, 좋은 디자인의 코드로 바꿀 수 있다. 따라서 리팩토링을 이용하면 처음부터 미리 모든 경우에 대해 고민하고, 필요할지 확실하지도 않은 유연성을 소프트웨어에 주기 위해 비용을 낭비할 필요가 없다.

개발할 때 아주 중요한 것이 절차지향, 객체지향, 집합지향 패러다임에 모두 익숙해지는 것이다. 분야에 따라서 객체지향이 필요없는 곳도 있고 집합지향이 필요없는 곳도 있다. 하지만 일반적인 웹개발에서는 세가지 모두에 능숙할 필요가 있다. 개인적인 경험으로는, 객체지향 패러다임으로의 전환이 가장 힘들다. 특정 문제 상황을 객체지향적으로 해결하는 것은 인간의 상식적인 사고를 많이 벗어난다는 느낌을 가지고 있다. (절차지향이 가장 상식적) 그래서 C++이나 Java나 C#으로 개발을 해도 옛날의 C코드와 똑같은 코드가 나와버리고 if-else 의 미로가 생기는 것이다.

이런 상황을 탈피하기 위한 첫걸음이 위의 두 책이 되겠다. 01년인가 원서로 두 책을 모두 읽었는데, 그야말로 대충격이었다. 일단 디자인 패턴책은 상당히 이해하기 어려웠다. 하지만 리팩토링책은 아주아주 쉽고 재밌었으며 실용적이었다. 특히 리팩토링 2장에서 아주 일반적인 절차지향 로직이 리팩토링 기법을 통해서 슬금슬금 아주 깔끔한 객체지향 코드로 변해가는 과정이 아주 충격적이었다. 이 책에 나오는 수많은 예제를 통해서 내가 그동안 얼마나 엄청난 스파게티를 만들어 왔는지 반성할 수 있었다.

디자인 패턴은 특정 문제상황을 객체지향적으로 설계해서 해결하는 훌륭한 생각의 단초를 제공해준다. 한마디로 객체지향 패러다임으로 전환하는데 아주 도움이 많이 된다. 물론 쉽지 않다. 기존의 사고의 틀을 깨야 하므로... 하지만 반드시 필요하다. 패턴에 감을 잡으면 개발속도도 빨라지고 버그도 적어진다.

위의 두 책을 본 후에는 다음 책을 보면 좋을 것 같다.
 엔터프라이즈 애플리케이션 아키텍처 패턴  마틴 파울러 지음, 송대국 옮김

이 책은 큰 규모의 웹서비스를 구성할 때 전체 아키텍쳐를 어떻게 잡아야 할지 가이드 라인을 제시해준다. 사실 이 책에서 권고하는대로 사이트를 구성하기는 좀 힘들다. 개발자들이 모두 패턴에 대해 전문가 수준이 되어야 하기 때문이다. 하지만 아키텍쳐의 큰 효과중의 하나가 개발자들간의 커뮤니케이션의 효율화임을 생각해본다면 위의 책을 보고 전체 아키텍쳐를 고민해보는 과정이 반드시 필요하다.

사실 위의 책 이전에 Pattern Oriented Software Architecure 1권을 봐두는게 좋다. 이 책에는 XP에서 말하는 메타포 수준의 아키텍쳐가 수백페이지에 걸쳐서 나와있다. (알라딘에 없다. 국내에 없다. 아마존으로 가야함) 아키텍쳐 스타일이라고도 부른다. 이 책의 장점이라면, 웹사이트뿐만 아니라 특정 영역의 솔루션을 개발할 때 기본적인 설계도를 제공해준다는데 있다. 엔터프라이즈 애플리케이션 아키텍쳐 패턴은 웹사이트가 레이어드 아키텍쳐로 개발된다는 것을 전제로 레이어 안의 설계를 위해서 어떻게 해야 하는지에 대한 지침을 제공한다면, POSA 1권은 그거 보다 좀 더 큰 수준, 레이어 아키텍쳐니 MVC니 파이프&필터니 블랙보드, 퍼블리쉬&서브스크라이브니 하는 패턴들이 나온다. 그 유명한 MVC도 사실 POSA 1권에 나오는 하나의 패턴에 불과하다. 이정도로 큰 규모의 패턴들을 다루는게 POSA 1권이다. 게다가 디자인 패턴책처럼 각 패턴의 말미에 어떤 솔루션을 개발할 때 사용되었다는 간략한 코멘트도 나온다. 옛날에 ETL툴 개발할 떄 이책에 나온 파이프&필터 아키텍쳐에서 핵심 아이디어를 얻었다. 가장 중요한 것을 해결하고 나니 그 뒤로는 상세설계&개발이 비교적 수월하게 풀려나간 경험이 있다. 물론 확장성/유연성도 아주 좋았다.

만약 당신이 네트웍 개발에 종사하고 있다고 하자. 네트웍 서버를 만들어야 하는데... 그렇다면 다음 책을 보면 된다.
C++ Network Programming Volume 1 - ACE와 패턴을 사용한 객체지향 네트워크 프로그래밍  더글라스 슈미츠 외 지음, 곽용재 옮김
수많은 하드웨어 플랫폼과 운영체제상에서 쓸 수 있도록 연구, 개발된 네트워킹 오픈소스 프레임워크 ACE(Adaptive Communication Environment)를 사용한 프로그래밍 방법을 알려주는 책으로, 복잡한 분산 시스템을 개발하고 최적화하기 위한 실용적인 해결책을 제시한다.
C++ Network Programming Volume 2 - ACE와 프레임워크를 이용한 체계적인 재사용 기법  더글라스 슈미츠 외 지음, 곽용재 외 옮김
<C++ Network Programming Volume 1>에서 네트워크 처리 기초 구성 요소인 ACE와 ACE Wrapper Facade 클래스에 대해서 소개했다면, 이번 Volume 2에서는 상위수준의 통신 서비스를 제공하기 위해 Wrapper Facade 위에 프레임워크를 어떻게 구축하는 가를 설명한다.

사실 위의 책은 Pattern Oriented Software Architecture 2권을 좀 더 친절하게 풀어쓴 것에 불과하다. 하지만 POSA 2권이 울나라에 없으니..-_-;;; POSA 2권은 위 두 책의 저자가 ACE 프레임웍을 만들면서 생각해낸 각종 네트웍 개발에 관한 패턴들을 담고 있다. ACE 프레임웍은 유닉스/윈도우에서 모두 돌아가는 비동기 통신 프레임웍이다. 나온지는 꽤 되었는데 한국에는 작년쯤부터 쓰이기 시작했다. 유닉스/윈도우의 시스템 콜을 모두 래핑해서 플랫폼 독립적인 코드가 돌도록 해준다. 이 프레임웍은 플랫폼 독립적인 메모리, IO, 소켓, 데이터타입등을 자체 제공한다. C++이라 매우 빠르다. 2002년에 ETL툴 만들때 이거를 처음 접했으니 그당시에 한국에서는 거의 처음이지 않았을까 싶다. 그때 ACE프레임웍 원저자랑 이멜 주고받으면서 버그도 잡고 그랬는데. 울팀 서버개발자들이 엄청난 천재들이어서 가능한 일이 아니었나 싶다. (난 ACE가지고 직접 개발은 못해보고 공부만 대충...)

위의 책들을 공부하고 나면 어떤 시스템이던 대략 감잡고 큰 설계를 해낼 수가 있다. 물론 OS나 DBMS를 만드는 수준까지야 힘들겠지만, 그 바로 위의 시스템 소프트웨어들, TP모니터나 웹서버, WAS서버등은 설계가능 할 것이고... 웹사이트나 각종 솔루션 설계는 상당히 쉽게 해낼 수 있을거라고 생각한다.

사실 위의 책들은 어디까지나 SW아키텍쳐에 국한한 얘기고 이거 이후에는 데이터 아키텍쳐(전사 데이터 모델링, 튜닝, 데이터 품질관리 등등의 이슈가 있다), 시스템 아키텍쳐(인프라에 해당하는 기계들 구성하고 배치하는 쪽일걸? 잘 모른다) 등등을 통달하면 엔터프라이즈 아키텍트라 이름붙일만 할 것이다. 이 수준까지 가면 미국같으면 연봉 10만달러 우습겠지만 한국에선 솔직히 잘 모르겠다. ㅎㅎㅎ

Posted by maceo

09 22, 2006 01:19 09 22, 2006 01:19
, , , , ,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/70

1TB를 한시간안에 로드하기

1TB 를 한시간안에 로드하기

http://blogs.msdn.com/sqlcat/archive/2006/05/19/602142.aspx
번역 : 박노철(maceo.park@gmail.com)

이 프로젝트는 SQL Server 2005 엔터프라이즈 에디션 (SP1 beta) 에서 60개의 병렬 입력파일에 대해서 BULK INSERT 를 사용해서 수행되었다. 각 파일의 크기는 약 16.67GB 이다. 최고 기록은 50분이다. HP는 TPC-C 테스트에 사용하는 기계를 하룻밤 빌려주었다. 1.6GHZ Itanuum2 CPU 64개가 달린 수퍼돔이었다. insert 테스트를 위해서 256GB 램을 장착했다. HP SAN 설정은 초당 14GB의 스루풋을 보여주었다. http://tpc.org/tpcc/results/tpcc_result_detail.asp?id=103082701 에서 상세한 설정을 찾아볼 수 있다.


BEST PRACTICES and LESSIONS LEARNED

  • 최대한 많은 수의 CPU를 사용하라. 32개의 CPU가 있으면 32개를 동시에 로딩하라. 8개면 8개를 로딩하라.
  • 만약 입력 파일을 생성하는 것을 조절할 수 있는 권한이 있으면 병렬로 로드하려는 스레드 갯수로 나눈 수만큼 파일크기가 동일하게 조절하라. switch 파티션 전략을 사용하고 싶으면 모든 레코드들이 하나의 파티션에 속하는 것을 확인하라.
  • 만약 작업을 SQL Server 머신에서 수행한다면 BCP 대신에 BULK INSERT 를 사용하라.
  • 추가적인 8~10% 의 속도개선을 위해서 테이블 파티셔닝을 사용하라. 단, 입력 파일들이 파티셔닝 함수에 적합하다는 것이 보장되어야 한다. (하나의 파일에 있는 모든 레코드가 같은 파티션에 있어야 함을 의미)
  • TABLOCK 을 사용하라.
  • 만약 복수개의 스트림을 하나의 테이블에 로드한다면 ROW PER BATCH = 2500 이나 그 근방의 값을 사용하라.

TEST SETUP

파일들은 database 와 동일한 SAN에 존재했다. 디스크 어레이는 달랐다. 하나의 드라이브 어레이에 12개의 파일들이 있었고 60개의 입력파일들을 핸들링하기 위해서 5개의 디스크 어레이가 필요했다. DB는 두개의 파일그룹과 96개의 파일을 가지고 있다. insert 테스트를 위해 사용된 테이블은 LINEITEM 이고, 자기 자신의 파일그룹에 존재하고 있다. 디스크상에는 바깥쪽 트랙에 위치한다.

DB는 BULK LOGGED 모드였다. 따라서 트랜잭션 로깅은 거의 일어나지 않았다. 익스텐트 할당과 관련된 메타데이터는 로깅되었지만 개개의 페이지 변화나 레코드 인서트는 기록되지 않았다.

입력파일을 | 를 컬럼 델미미터로 사용하는 문자열 파일이다. 이러한 flatfile 들은 DBGen 을 이용해 만들어졌다. DBGen 은 TPC 협회에서 제공하는 표준 도구다. flatfile 는 깨끗한 것으로 간주할 수 있다. 행길이는 가변 길이였는데, 평균 130바이트 정도 된다.

최종 설정에서 60개의 job을 만들었고, 각각은 하나의 BULK INSERT 를 담고 있었다. 굳이 여러개의 쿼리 윈도우를 열지않고 작업을 컨트롤하기 위해서 이렇게 했다. 각각의 job 을 컨트롤하기 위해서 sp_startjob 이 사용되었다.

최초의 테스트는 ROWS PER BATCH=2500 으로 해서 하나의 테이블에 대해서 수행되었다. 40개의 스레드가 시작되기 전에는 블러킹이 거의 없었다. 배치 사이즈가 2500이었기 때문에 락 유지시간은 상당히 짧았다.  Data Management View 를 통해서 보니 하나의 테이블에 대한 익스텐트 할당때문에 락이 잡혔다. 이 테스트를 조금씩 바꿔가면서 해보았는데 대체로 65분 안에 끝났다. 익스텐트 할당으로 인한 대기를 피하기 위해서 다음 테스트는 복수개의 테이블에 대해서 수행되었다.

다음 테스트는 각각의 입력에 대해서 각각의 테이블을 사용하는 것으로 수행되었다. 각 테이블은 하나의 파티션을 가지고 있었고 최종적으로 파티션들은 60개의 파티션을 가진 하나의 거대한 테이블로 switch in 되었다. (스위칭은 SQL 2005 테이블 파티셔닝에서 사용되는 새로운 용어이다) 스위칭은 메타데이터 스위치에 불과하기 때문에 매우 빠르다. 테스트결과 한번 스위칭하는데 평균 22~35ms 정도 걸렸다. 여기서 어려운 점은 각 입력파일이 정말로 그 파티션에 속하는지를 확인하는 작업이다. 이 테스트에서 배치사이즈는 테스트결과에 어떤 차이를 만들어내지 못했다. 왜냐하면 테이블당 하나의 BULK INSERT 스레드가 사용되기 때문이다. TABLOCK 은 잠금 관리를 회피하기 위해서 매우 중요하다.

최종결과를 볼 때 각각의 테이블로 분리함으로써 8~10%의 향상을 이룰 수 있었다. 이게 바로 1TB를 로드하는데 50분이 걸린 시나리오다. 인덱스 빌드나 파티션 검증을 위한 제약조건 생성을 위한 시간은 없았다. 다음 테스트로 미룬다.


CPU BOTTLENECK

주된 제약조건은 CPU였다. IO가 아니었다. SAN은 초당 14GB의 스루풋을 가진다. SQLIO를 사용해서 드라이브의 최대 스루풋을 측정해볼 수 있다. 우리의 테스트에서 BULK INSERT를 돌리는 60개의 스레드에 대해서 최대 초당 333MB의 쓰기 작업이 일어났다. 이는 초당 210만개 조금 넘게 BULK COPY하는 것을 의미한다. PERFMON을 사용하여 이 카운터를 관찰했다.

하나의 BULK INSERT 스레드는 유휴 CPU 를 99~100% 사용한다. 다음 job은 다른 CPU를 사용했다. 한참 바쁜 CPU에 스케쥴링되지는 않는 것으로 보였다.

TEST PROCESS

첫번째 테스트는 한번에 하나의 job 을 시작해서 정상상태에서 도달해서 작동하도록 내버려 두는 것으로 시작했다. 모든 측정은 기록되었고 다른 job이 시작되었다. 관찰하고 있던 카운터값의 증가는 매우 예측가능한 수준이었다. 그러나 정확하게 선형적이지는 않았다. 즉, 두번째 job이 첫번째 job이 도는 속도로 돌지는 않았다. 사실, 로그곡선의 형태로 판명되었고 60개의 job이 동시에 돌 때는 아주 평평했다.

첫번째 테스트는 BCP가 CPU를 몇%정도 더 사용한다는 것을 알아채기 전까지는 BCP를 사용해서 진행되었다. 55개의 job이 실행될 때까지 CPU 총사용량은 100%였다. 그래서 BULK INSERT 로 바꿨는데, 이렇게 하면 import 스레드가 SQL Server process 안에서 돌아간다. BULK INSERT로 바꾼 후에 60개의 job을 동시에 돌릴 수 있었고, 60개를 돌릴때까지 스루풋은 계속 증가했다. 이때 CPU사용량은 95%를 유지했다. 61~64개의 job은 60개일때와 스루풋이 거의 똑같다.

첫번째 테스트 도중, 8~9GB짜리 파일이 96개 있었다. 동시에 60개의 job을 돌리지만 않는다면, 첫번째 48개의 파일들을 30분안에 로딩할 수 있었고 다른 49개도 마찬가지였다. 60분에 1TB를 로딩하는 것은 꽤 훌륭한 결과다.

일단 CPU가 제약조건이라는 것을 안 이후로, 60개의 파일을 16.67GB로 만들었다. 이렇게 하니까 최고 50분이 나왔다. 모든 고객들이 입력파일에 대한 세세한 권한을 가질 수는 없기 때문에 이런 테스트는 만들어진 측면이 있다. 초반부에 언급했듯이 입력파일들은 큰 테이블을 위해서 설계된 최종 파티셔닝 scheme 에 정확하게 들어맞았다.

최종 테스트는 CPU 밸런싱이 만족할만한 수준에 있는지 확인하기 위해 60개의 job을 동시에 돌리는 것이었다. 결과는 괜찮았다. 이는 동시에 두개의 BULK INSERT 스레드가 하나의 CPU를 사용하지 않음을 의미한다. SQL product team의 개발자들은 UMS스케줄러당 하나의 bulk command만 수행하도록 UMS스케줄러를 특별히 체크한다고 이야기해주었다. 물론 CPU갯수보다 더 많은 명령을 돌리면 CPU당 복수개의 bulk command를 할당할 것이다.

NOT FINISHED YET

여기에서 우리는 모든 데이트를 60개의 분리된 테이블에 가지고 있었다. 이것은 로컬 파티션드 뷰를 사용하기 원하는 사람들에게는 좋은 시나리오다. (테이블들에 대해서 union all 을 하는 하나의 뷰를 만드는 것) 

테이블 파티셔닝을 사용하기 원하는 고객들은 모든 파티션들을 하나의 테이블로 모으기 위해서 몇가지 단계를 더 거쳐야 한다. 다음과 같다.

  1. Create a File Scheme 파일 Scheme 을 생성
  2. Create a Partition Function   파티션 함수를 생성
  3. Create a clustered index on each file  각 파일에 클러스터드 인덱스를 생성
  4. Create the check constraint that will be used for partitioning.  파티셔닝을 위해 사용되는 제약조건을 생성
  5. Switch the partitions into the final large table.  각 파티션들을 하나의 큰 테이블로 스위칭

제약조건을 걸기전에 인덱스를 생성하는 이유가 있다. 우리가 이 두가지 작업의 순서를 바꾸게 되면, 제약조건에 맞는지 검사하기 위해서 테이블 스캔이 유발될 것이다. 클러스터드 인덱스를 먼저 생성함으로써 제약조건은 모든 행들이 제약조건에 맞는지 검사하기 위해서 첫번째 값과 마지막 값만 검사하면 된다.

NEXT TESTS

다음 테스트로 무엇을 해볼 것인지 수많은 아이디어가 있다 하지만 이걸 하기 위해서 TPC-H run 사이에 하룻밤만 시간을 빌려왔기 때문에 머신이 사용가능해지는 다음 시간까지 기다려야만 한다. 하지만 주어진 시스템 가용성 한도 내에서 HP는 이런 테스트를 할 수 있도록 해주었다. 실제로는 패턴이 매우 예측가능하기 때문에 다른 테스트는 패턴과 타이밍을 보기 위해서 더 적은 CPU를 가진 머신에서 이뤄질 수도 있다. 물론 많은 CPU를 가진 것이 아니라면 1TB를 로딩하는데 1시간에 끝나지는 않을 것이다.

  • SQL Agent와 SQL Server가 파일을 직접 읽지 않아도 되도록 BCP나 BULK insert 를 다른 클라이언트 머신에서 수행.
  • 네트웍이 끼어들어가면 패턴이 어떻게 변하는지 모기 위해서 입력파일을 다른 컴퓨터로 이동.
  • SSIS의 bulk insert task를 이용해서 테스트. 이것을 SQL Server 기계의 CPU부담을 낮춰주기 위해서 다른 기계에서 수행. 만약 이것을 SQL Server 머신에서 수행한다면 BCP를 사용하는 것과 거의 동일한 결과가 나올 것임.
  • 파일에 인덱스를 생성.
  • 더 작은 기계에서 수행. 모든 고객들이 64-way 머신을 가지고 있지는 않을 것이기 때문.
  • 입력파일들을 미리 정렬해놓고 로딩전에 클러스터드 인덱스를 먼저 만듦. 만약 미리 정렬이 되어 있다면 인덱스 생성 시간을 절약해줄 것임.
  • NUMA 설정이 어떤 영향이 있는지 관찰. CPU 병목현상이 있다면 그다지 도움될 것 같지는 않아 보임. 하지만 해당 노드에 foreign memory(NUMA아키텍쳐에서 다른 셀의 CPU를 뜻함)가 할당된다면 더 느려질 것이다. foreign memory 할당을 피하는 방법이 있다. 슬라바 오크의 블로그를 참조.(http://blogs.msdn.com/slavao)

감사의 말씀 : MS SQL Server product group 의 Sunil Agarwal 와 그의 팀, HP의 Mike Fitzner 에게 감사드립니다.

enjoy -- Kevin

Published Friday, May 19, 2006 9:58 PM by kevincox
Filed Under: Performance and Scalability

Comments
# Microsoft SQL Server Development Customer Advisory Team - Load 1TB in less than 1 hour @ Sunday, May 21, 2006 7:46 PM
Professional Association for SQL Server (PASS) SIG

# SQL Server 2005: Load 1TB in less than 1 hour @ Tuesday, May 23, 2006 5:50 AM
STEFANO DEMILIANI WeBlog

# re: Load 1TB in less than 1 hour @ Wednesday, May 24, 2006 3:45 PM
흥미롭습니다. 추가적인 테스트를 기대합니다 (특히 SSIS테스트요) 그런데 다음 사항에 대해서 더 상세하게 설명해주시겠어요?

“Use ROWS PER BATCH = 2500, or something near this if you are importing multiple streams into one table.”

어떻게 이 값이 제일 좋은 값이라고 결론내신건지요? 테스트에 사용된 데이터에만 해당하는 수치는 아닌가요? 제가 큰 데이터를 마이그레이션 테스트할 때는 정확한 배치 사이즈는 테이블의 데이터 타입을 관찰함으로써 결정할 수 있었습니다. SQL 2000 에서 최대 로그 블럭은 60KB입니다. 따라서 저는 배치당 60KB 넘게 insert 하지 않도록 배치 사이즈를 조절합니다.(의역했음)

60KB limit에 도달하기 위해서는 몇개의 익스텐트 할당이 필요한가요?(뭔 소린지 잘 모르겠음. 익스텐트당 64KB아닌가..?)

당신의 테스트에서는 익스텐트 할당 대기와 관련된 여러 이슈들을 언급한 것 만큼은 이건 크게 고려되지 않은 것 같네요. 하지만 더 작은 시스템에서는 60KB 로그 플러쉬와 관련해 BULK INSERT 사이즈를 조정하는 법을 이해하는 것이 좋을 것 같습니다.


Bert

# re: Load 1TB in less than 1 hour @ Wednesday, May 24, 2006 8:23 PM
Amazing statistics.. Interesting that disk IO on the SAN configuration did NOT turn out to be the bottleneck in this case. What was the memory consumption during this test?
Ted Malone

# re: Load 1TB in less than 1 hour @ Wednesday, May 24, 2006 9:50 PM
Response to Bert: 배치당 2500 rows 는 lock escalation 을 피하기 위해서 사용되었습니다.

잘 모르겠습니다. 그리고 걱정할만큼 중요한 속도저하인지도 잘 모르겠군요.

불행하게도 디스크 공간 확보를 위해서 perfmon 로그를 지웠습니다. 256GB 메모리의 거의 다 사용하지는 않았던 것 같습니다. 메모리 대기가 있다면 더 주의하도록 하지요.

kevincox

# re: Load 1TB in less than 1 hour @ Monday, May 29, 2006 12:46 PM
NUMA에 따른 영향에 대해서 관심이 있습니다. SQL Server는 몇개의 log 기록 스레드를 사용할 수 있나요? 만약 하나 이상이라면 affinity bw(???) 를 조정할 수 있나요? 만약 로그 기록 스레드가 동일한 NUMA노드나 동일한 프로세서/코어에 존재하는 것이 어떤 효용이 있다요? 컨텍스트 스위칭과 스레드간의 통신의 트레이드 오프는 어떤가요?(???) 만약 하이퍼 스레딩 머신이라면 로그 기록 스레드가 insert스레드와 다른 논리 프로세서에 있는 것이 어떤 효용이 있습니까?

# re: Load 1TB in less than 1 hour @ Tuesday, May 30, 2006 9:29 AM
SQL Server 2005 에서 최대 페이지 사이즈는 얼마인가요? 변경가능한가요?

Francisco


Posted by maceo

09 19, 2006 14:30 09 19, 2006 14:30
, , , ,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/69

XP팀의 작업실

XP팀의 작업실

우아 멋지삼~! @.@

CVS체크인->자동빌드->단위테스트->통합테스트 가 자동으로 진행된다는게 대단.
역시 XP의 정수? 는 TDD와 테스트 자동화가 아닐까 싶군.
저런 환경에서 개발을 못해본게 참으로 안타깝네.

Posted by maceo

08 29, 2006 09:56 08 29, 2006 09:56
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/66

EBay: The OS for E-Commerce?

이베이 한참 잘나가던 2006년의 글이다. web2.0 바람 한참 불 때 번역하다가 오늘에사 마무리한다. 지금 읽어보니 격세지감이 느껴지는군. web2.0 광풍이 몰아치고 난 후에도 플랫폼으로써의 웹은 여전히 유효한 명제이지만 그걸 제대로 해내고 있는 곳은 생각보다 많지 않다. 오히려 이베이는 내리막이고 아마존이 플랫폼 사업을 훨씬 더 잘해내고 있지. 읽다보면 같은 비전을 가지고 있는데 왜 이렇게 결과물은 다른걸까? 아마존 S3, EC2, WebServices,Fullfillment 등 그들은 자신들의 플랫폼을 하나씩 서비스화해서 꺼내놓고 있는데 이베이는 2년전이나 지금이나... 그다지 변한게 없다. 회사 문화의 차인가.... 실행력의 차이인가?

통찰력있는 전략/비전 + 칼같은 실행력

중에 전략/비전은 미비하고 실행력만 있으면 그래도 근근히 버틸 수는 있겠으나
전략/비전은 창대하나 실행력이 없으면 말만 번지르르하고 망해버린다는 사례가 되어버리는 것은 아닌가 모르겠다...  ㅎㅎㅎ
(SKT처럼 확실한 캐쉬카우 + 통찰력없는 전략/비전 + 아예 전무한 실행력을 가진 조직은 도대체 뭐라고 해야하나? 신도 질투하는 직장, 공기업??  ㅋㅋㅋ)

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


http://www.technologyreview.com/read_article.aspx?id=17280&ch=biztech


EBay: The OS for E-Commerce?

Microsoft has had a research division since the early 1990s. Google's programming staff spends 20 percent of its time on R&D. Even Yahoo has a growing research division (see "Yahoo Ramps Up Research"). So why not eBay?

마이크로소프트는 90년대 초반부터 연구 부서를 가지고 있었다. 구글의 프로그래밍 인력들은 자신들의 시간중 20% R&D 에 사용한다. 심지어 야후의 연구 부서도 규모가 커지고 있다. eBay 가 그렇게 해서는 안될 이유가 무엇인가?

In fact, the online auction giant has a research outfit, although it's little more than a year old. Known as eBay Research Labs, it began as a corps of programmers called the Advanced Technology Group.

사실, 고작 1년 조금 더 되었지만 eBay eBay Reseach Lab이라는 연구 부서가 있다. 이 연구소는 Advanced Technology Group 라고 불리는 프로그래머 단체로부터 시작되었다.


For its tender age, the division has outsized ambitions. Its senior director, Eric Billingsley, a former nuclear engineer and veteran of search industry pioneer AltaVista, believes eBay will become a "common platform" for all kinds of online commerce, allowing people to build on and profit from customized tools that tap into eBay's massive inventory and customer-service infrastructure.

시작초기부터 Reseach Lab 은 원대한 포부를 드러냈다. 시니어 디렉터인 Eric BillingsleyeBay가 앞으로 사람들이 eBay의 거대한 물품목록과 고객 서비스 인프라를 활용하여 커스터마이즈된 도구를 만들고, 또한 그것으로부터 이윤을 창출할 수 있는 온라인 상거래의 공통 플랫폼 이 될 것이라고 믿고 있다.

By cultivating new ideas inside the company and also reaching out to third-party developers, Billingsley is trying to position eBay as the New York City of the Internet economy -- the place every independent developer or startup CEO with e-commerce ambitions has to go to make it big.

사내의 새로운 아이디어를 육성하고 서드파티 개발자들과 접촉하면서 Billingsley eBay를 인터넷 경제의 뉴욕시로 자리매김 하려고 한다. 바로 전자상거래에 야망을 가진 모든 독립개발자들이나 신생기업 CEO들이 성공하기 위해서 거쳐야만 하는 그런 곳으로 만드려고 하는 것이다.


Meanwhile, the lab's researchers are analyzing eBay from within and without -- improving the backend hardware and software that keep the existing online marketplace running, while coming up with new ways to make users feel more at home when selling and buying on the site.

그동안 연구소 인력들은 eBay를 안팎에서 분석하고 있다. 사람들이 보다 편리하게 물건을 사고 팔 수 있는 새로운 방법을 제안하는 한편, 현존하는 온라인 마켓플레이스가 돌아가게 하는 뒷단의 하드웨어와 소프트웨어를 향상시키고 있다.


Technology Review senior editor Wade Roush interviewed Billingsley at eBay's headquarters in San Jose on August 2.

Technology Review 의 편집장 Wade Roush 는 지난 8 2 San Jose의 eBay에서 Billingsley를 인터뷰했다.


Technology Review: What was your first big project within the labs?

연구소에서 당신의 첫번째 큰 프로젝트가 무엇이었습니까?


Eric Billingsley: The first one we really dug into, as the Advanced Technology Group, was the search engine for eBay. Back then, it would take nine hours to update eBay's index. Searches were extremely slow, and it was becoming a very expensive part of the infrastructure. Now, when you place a bid it's a matter of seconds before it shows up in the index. So right off the bat, we started having some impact. And that got us some clout and made it possible for us to start doing some other things within eBay.

Advanced Technology Group의 이름으로 우리가 처음으로 파고든 것은 검색엔진이었습니다. 그당시에는 eBay전체의 인덱스를 업데이트하는데 9시간이 걸렸습니다. 검색은 엄청나게 느렸죠. 그리고 인프라에서 아주 비용이 많이 드는 부분이 되어가고 있었습니다. 지금은, 만약 당신이 입찰을 하게 되면 인덱스에 나타나는데 불과 몇초면 됩니다. 즉시 우리는 어떤 충격을 받았습니다. 그리고 이 일은 우리에게 어느 정도의 영향력을 가져다 주었고 eBay내부에서 다른 것들을 시작할 수 있게 해주었습니다.


TR: How many people do you have in the labs now, and what types?

연구소에는 얼마나 많은 인력들이 있고, 어떤 타입인지요?


EB: I'm a nuclear engineer by training. I've got two physicists, I've got an anthropologist, I've got a number of computer science people of course. Mathematicians, statisticians, computational linguistics, machine learning. Right now it's a very small team.

저는 원자력 엔지니어로 교육받았습니다. 물리학자가 두명있고, 인류학자도 있습니다. 물론 전산전공자들은 여러명입니다. 수학자, 통계학자, 컴퓨터 언어학자, 기계 학습 전공자 등등이 있죠. 지금은 아주 작은 팀입니다.

TR: It sounds like you're not a classic research division, where there are lots of PhDs off in a building thinking of cool ideas.

온갖 멋진 아이디어를 생각해내는 박사님들로 가득찬 전통적인 연구부서같지는 않군요.


EB: That's what makes it an exciting job for my guys. I don't want to hire people who want to be in an ivory tower. We want people who are going to invent the technology that's going to power everybody's infrastructure in five years.

그게 바로 저와 같이 일하는 친구들을 즐겁게 하는 이유입니다. 저는 상아탑에만 있고자 하는 사람들을 고용하고 싶지는 않습니다. 우리는 기술을 발명하고 모든 사람의 인프라를 5년내에 향상시킬 수 있는 사람을 원합니다.


With that in mind, one thing we're looking at is how we can apply some ideas from social networking. We're taking the feedback of our users and using that to actually help the community find what they find most interesting. Have you looked at eBay Express yet? That's the first iteration of some of the finding work that we're going to be putting out over the next year.

그런 점을 염두에 두고서 우리가 주목하는 것중에 하나는, 어떻게 하면 소셜 네트워킹에서 시작한 아이디어들을 적용할 수 있을까 하는 것입니다. 우리는 유저들의 피드백을 받고, 커뮤니티 구성원들이 그들이 가장 흥미로워할만한 것들을 찾는데 실제로 도움이 되도록 그것들을 이용하려고 합니다. eBay Express 혹시 보셨나요? 내년 1년간 저희가 출시할 서비스중 첫번째 iteration입니다


(
역자주:iteration iterative software development process에서 매 한번한번의 반복주기를 뜻하는 말이다. 기획->분석->설계->테스팅&디버깅->출시 의 전통적인 폭포수 모델과는 달리 iterative software development process 는 전체 소프트웨어를 여러 번의 작은 iteration으로 나누어 개발한다. 하나의 iteration이 끝나면 그것이 전체 기능중 일부가 구현된 하나의 독립된 제품이다.)


Normally at eBay you'll find quite a mixture of things. Let's enter the search term "iPod nano." [Billingsley turns to his laptop.] You get earphones, chargers, covers, armbands -- pretty much anything except an iPod. But at eBay Express we know [from studying previous users' behaviors] you either want iPod accessories or you don't, so those are the choices you get. That allows you to very rapidly zero in on what you're interested in.

eBay에서 수많은 것들이 혼합된 것을 알 수 있을 겁니다. iPod nano라는 검색어를 입력해보지요. 이어폰, 충전기, 커버, 암밴드 등 iPod말고도 꽤 많은 것들이 나옵니다. 하지만 eBay Express에서는(지난 몇 년간 사용자 행태를 연구한 끝에) 당신은 iPod의 악세사리를 원하거나 원하지 않거나 둘 중 하나라는 것을 이제 알고 있습니다. 사용자는 이제 관심이 있는 것에 매우 빠르게 다가갈 수 있습니다.

TR: So you're giving people a solution for the frustration of getting ten different kinds of things when they're really just looking for an iPod. Are there other frustrations or inefficiencies that you're trying to help people solve?

그렇다는 것은 사용자들이 정말로 iPod를 찾고 있을 때, 사용자들을 혼란에 빠뜨릴 수 있는 온갖 종류의 물건들이 함께 나오는 문제에 대한 해결책을 제시하고 있다는 말씀이군요. 이것 말고도 또다른 혼란이나 비효율은 없나요?


EB: We're trying to get better at understanding the intent of a buyer. The way we see it, if you're looking for a piece of electronics, you are thinking about very different things than if you're looking for a glass collectible. You're thinking about, how does it fit into my living room? Does it take U.S. power? What's the shipping cost going to be on this thing? You're going to get a list of products and you're going to make a comparison between this, that, and the other.

우리는 구매자들의 의도를 더 잘 이해하는데 노력을 기울이고 있습니다. 당신이 만약 전자제품을 찾는다면, 아마도 유리 수집품을 찾을 때보다 훨씬 더 여러 가지 사항을 생각하고 있을 겁니다. 이게 내 거실에 맞을까? 미국 전원 표준에 맞을까? 배송료는 어떻게 되지? 등등 말이지요. 여러 상품들을 볼 것이고 이것저것 비교를 하게 되겠지요.


But when you are searching for a collectible, you're thinking about, what do I already own, and how do I find more like that or something completely different? What's of value to you may be very different from what's of value to someone else. We're trying to get a little further down the road of making those into customized experiences.

하지만 수집품을 찾을 때는 이런 것들을 염두에 두겠죠. 내가 이미 가지고 있는 건가? 아니면, 이것과 비슷한 것, 또는 완전히 다른 것을 어떻게 찾을 수 있을까? 당신에게 가치있는 것이 다른 사람에게 가치있는 것과 매우 다를 수 있습니다. 우리는 우리는 이러한 고객별로 다른 경험칙들을 좀 더 연구하려고 합니다.


TR: Okay. I own an old wooden stereoscope, from 1905. You can buy cards for them that have two photographs taken from slightly different angles. It sounds like you want to make it so that I can click on a few buttons and get a special "Stereoscope Store" to find more cards.

알겠습니다.  저는 1905년에 만들어진 오래된 입체경을 가지고 있습니다. 당신은 입체경에 사용하기 위해서 약간 다른 각도에서 촬영된 사진 두장이 있는 카드를 살 수 있습니다. 이건 마치 제가 클릭 몇번만 더 하면 더 많은 카드를 ㅊ자을 수 있는 특별 "입체경 가게" 를 가질 수 있다는 것처럼 들리는군요.


EB: Exactly. But my real goal is to create a platform that allows third-party developers to develop that store for us and that allows them to profit from it. I want to build eBay such that it's almost a plug-in architecture, and we can allow developers to go in and create these perfect buying experiences within these little niche markets. Because that "long tail" is huge. And we're only beginning to tap it.
EB: 정확합니다. 하지만 저의 진짜 목표는 모든 서드 파티 개발자들이 저희를 위해서 그런 가게들을 개발하고 거기서 돈을 벌 수 있는 플랫폼을 만드는 것입니다. 저는 이베이를 플러그인 아키텍쳐로 만들고 싶고, 우리는 개발자들이 들어와서 이러한 조그만 니치 마겟 안해서 완벽한 구매 경험을 만들어내길 원합니다. 왜냐하면 그런 "롱테일"들은 거대하기 땜누이죠. 우리는 이제 막 탐색단계에 들어섰을 뿐입니다.

TR: Say more about this plug-in architecture and how it would benefit outside developers.

TR: 플러그인 아키텍가 무엇이고 외부 개발자들에게 어떤 혜택을 줄 수 있는지 좀 더 설명해주시죠.

EB: This is still in early phases, and I'm talking about it openly because I'm looking for the rest of the Internet community to help us with this. I want to enable people to build a business on top of a business on top of a business. I want to bring our infrastructure stack to the entire developer community such that they are no longer limited by having to buy and run their own infrastructure. Ideally, we want to take it to the point where a single developer anywhere in the world can make a living developing applications for a company website and never actually be an employee of that company.

EB: 이건 여전히 초기 단계에 있는데요, 저희를 도와줄만한 인터넷 커뮤니티를 찾고 있기 때문에 여기에 대해서 공개적으로 이야기하고 있습니다. 저는 비즈니스 위에 비즈니스 위에 비즈니스를 만들 수 있도록 하고 싶습니다. 우리는 우리의 인프라스트럭쳐를 전체 개발자 커뮤니티에 공개하고 싶고, 그럼으로써 개발자들이 그들만의 인프라를 구매하고 운영함으로써 발생하는 한계를 없애고 싶습니다. 이상적으로는 우리는 세계 어느 곳에 위치한 개발자던지 어떤 회사에 속해있지 않으면서도 그 회사를 위한 어플리케이션을 개발해서 생계를 유지할 수 있는데까지 가고 싶습니다.

TR: You have some peers not too far away from this campus that are doing similar things. With S3, Amazon is encouraging people to basically offload all their database operations to Amazon's excess capacity (see "The Internet Is Your Next Hard Drive"). And you've got Google persuading people to upload their entire portfolio or inventory into Google Base.

TR: 당신은 여기서 그리 멀리 떨어지지 않은 곳에서 비슷한 일을 하는 친구들을 알고 있죠. 아마존 S3는 사람들이 그들의 데이터 작업을 아마존의 엄청한 서버 용량위에서 수행하라고 부추기고 있죠. 그리고 구글도 구글 베이스에 포트폴리오나 상품 재고들을 올라라고 하고 있구요.

EB: But all of those are very limited services. It's all about, "Give us your data." And from research labs, I can tell you, data is power. So of course it makes sense for companies to do that. But what I want to do is bring the traffic to the developer. I don't expect anybody to do anything for free. When you list something with eBay, it's because you want to make money off that transaction. We have people who make their livings doing that. What I want to do is expand the types of people who can do that. I want not only people who have an inventory of products, but also people who have an inventory of ideas, education, and ability.

EB: 하지만 이것들은 매우 제한적인 서비스입니다. 그건 순전히 "당신의 데이터를 내놔라" 라는 것입니다. 데이터는 힘이라고 명확하게 말씀드릴 수 있습니다. 따라서 회사들이 이런 일을 하는 것은 이해가 됩니다. 하지만 제가 하고자 하는 것은 개발자들에게 트래픽을 몰아주는 것입니다. 저는 누가 공짜로 뭔가를 하기를 기대하지는 않습니다. 만약 이베이에 뭔가를 올린다면, 당신은 거기서 돈을 벌기를 원할겁니다. 이베이에는 그걸로 생계를 유지하는 사람들이 많습니다. 제가 하고자 하는 바는 그런 일을 할 수 있는 사람들을 좀 더 확대하는 것입니다. 저는 비단 상품을 판매하는 사람들 뿐만 아니라 아이디어, 교육이나 다른 어떤 능력을 가진 사람들까지 그렇게 하도록 하고 싶은겁니다.

TR: And these new applications you want these people to build -- do they have to have something to do with selling?

TR: 그런 사람들이 만들 새로운 어플리케이션들 말입니다, 그것들은 판매활동과 관련이 있는 것인가요??

EB: I think everybody has their purpose in life, and eBay's purpose is to pioneer new communities built on commerce. Commerce is behind almost every aspect of modern life. I don't see how that limits us in any way.

TR: You said that you guys brought yourselves into existence by proving that you could rework the search mechanism on the site. I'm wondering whether at the same time there might have been a sense that eBay was reaching a certain size or a certain revenue level where it really ought to have an R&D operation.

EB: 모든 사람은 저마다의 목적이 있다고 생각합니다. 이베이의 목표는 상거래위에서 새로운 커뮤니티를 발굴해내는 것입니다. 상거래는 오늘날의 일상의 거의 모든 부분에 존재합니다.

TR:당신들은 사이트의 검색 메카니즘을 바꿔져 존재 가치를 증명했다고 했습니다. 저는 동시에 이런 의문도 가지고 있습니다. 이베이는 R&D 기능을 가져야할만큼의 사이즈나 매출 수준에 도달한 것인가? 하는 겁니다.

EB: I'm sure you've heard about the "train seat" model at eBay. The train model is that we completely re-release the entire eBay site every two weeks. We just launched Train 472 on Monday, so everybody who had seats on that train saw their project go live on the site this week. That gives us predictability -- we know [when trains will arrive] a year ahead of time. The problem then becomes that our engineers are booked a year out, and there's not much wiggle room. So we've always had in the back of our minds that you need to have an extra set of resources -- people who are thinking about not just the business ideas, but how we can take new technologies and create new ideas that we can then feed back to the business.

EB: 이베이의 "열차좌석" 모델에 대해서 들어보셨지요? 열차 모델은 우리가 이주일에 한번씩 이베이 사이트 전체를 리-릴리즈한다는 것입니다. 우리는 월요일에 Train 472를 론치했습니다. 그 열차에 탑승한 사람들은 이번주에 자신들의 프로젝트가 사이트에 올라가는 것을 보게 될 겁니다. 이 과정은 우리에게 예측가능성을 선사합니다. 우리는 언제 열차가 도착할지 1년전에 알고 있습니다. 문제는 우리의 엔지니어들이 1년전에 이미 예약이 되어버린다는 것이고, 다른 것을 할 여유가 별로 없다는데 있습니다. 그리서 우리는 항상 마음속 깊이 또다른 리소스가 있어야 한다는 생각을 하고 있었습니다. 비즈니스 아이디어 뿐만 아니라 새로운 기술을 배워서 새로운 아이디어를 만들고, 다시 그것을 비즈니스에 반영하는 사람들 말이죠.

TR: So the folks in the research lab aren't assigned to train seats.

TR:그러면 리서치 랩에 있는 사람들은 열차좌석에 할당되지 않는가보군요?

EB: No.

EB:아닙니다.

TR: With all of the new features you're building, you're making it possible for people to spend a lot more time on eBay.

TR:당신들이 구축중인 신기능들이 완료되면 사람들이 이베이에서 훨씬 더 많은 시간을 보내는 것이 가능하겠군요.

EB: Well, I'm hoping that by spending more time on eBay, they'll have a better life as a result.

EB: 저는 이베이에서 더 많은 시간을 보냄으로써 저 좋은 삶이 되길 원합니다.

TR: Or they'll have more stuff. One or the other.

TR:아니면 물건 한두개를 더 사게되거나요.

EB: Some people feel complete once they've got that complete collection. I want to make them feel complete.

EB: 어떤 사람들은 완전한 컬렉션을 소유하게 되면 충만함을 느낍니다. 저는 그 사람들을 충만함으로 가득차게 하고 싶습니다.

Copyright Technology Review 2006.

Posted by maceo

08 10, 2006 23:57 08 10, 2006 23:57
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/62

오늘 마이그레이션 테스트를 하다가 알아낸 사실.

다음과 같은 쿼리가 있다고 하자.

select col1
, col2
, dbo.uf_test_function(col3)
into #temp_table
from VERY_BIG_TABLE a
inner join SMALL_TABLE b on a.col1 = b.col1
inner join BIG_TABLE c on b.col1 = c.col1
inner join BIG_TABLE d on c.col2 = d.col2
option(maxdop 4)

VERY_BIG_TABLE 의 데이터 갯수는  1억건, BIG_TABLE 의 갯수는 1천만건이다.
데이터 마이그레이션 중이므로 당연히 CPU 4개를 써서 한꺼번에 읽어서 hash join 으로 처리하기를 기대하고 위와 같이 만들었다. 그런데 돌려보니 평소에 걸리던 것보다 시간이 엄청 오래 걸린다. 실행계획을 보니 병렬 계획을 세우지 못하는게 아닌가!

도대체 이게 무슨 일인가 하여 테이블을 하나하나 빼가면서 여러 모로 살펴본 결과 원인은 두가지였다.

1. BIG_TABLE 에 대해서 self-join 을 한다.
2. select 문에 dbo.uf_test_function 이 있다.

믿기지가 않겠지만 정말로 일어난 일이다. SQL Server 2000 sp4 에서 발생했다.

1번에 대해서는 그럴수도 있겠다는 생각이 든다. SQL Server 는 아주 가끔 병렬 계획을 세워서 쿼리를 수행하다가 Intra Query Paralleism Deadlock 을 일으킨다. 즉, 복수개의 CPU 들이 쿼리를 처리하다가 지들끼리 데드락을 잡아서 쿼리가 실패하는 경우다. 아무래도 복수개의 CPU가 같은 테이블을 self-join 해야 하는 상황이 되다보니 옵티마이저가 데드락을 우려하여 알아서 병렬 계획을 안세운 것이 아닌가 하는 생각이 든다.

2번에 대해서는... 전혀 알 수 없다. 도대체 function 하고 병렬 계획하고 무슨 상관이람-_-;
function 은 실행계획에 아예 나오지도 않는데 뭐 그런 문제랑 관련이 있는건지.. 흠....

Posted by maceo

08 3, 2006 19:09 08 3, 2006 19:09
, ,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/60

Stored Procedure 작성시 에러 처리 팁

Stored Procedure 작성시 에러 처리 팁

일러두기. 본문서는 기배포된 중첩 트랜잭션 처리 가이드와 함께 읽으면 좋습니다.

1. @@error 와 @@rowcount 를 이용한 에러 처리

@@error : SQL문 실행도중 어떤 이유로 에러가 발생했을 때 0 이 아닌 값으로 세팅되는 시스템 함수. 에러가 발생했다가 단 한줄이라도 다음 문장이 성공하면 0 으로 세팅됨.

@@rowcount : select, insert, delete, update, set 문이 성공한 후에 몇 행을 처리했는지 세팅되는 함수.

일반적으로 SP 안에서 에러처리는 다음과 같은 패턴으로 이루어집니다.

UPDATE DEPT SET DEPT_NM = '테스트부서' WHERE DEPT = 'AD' 

if @@error <> 0 or @@rowcount <> 1  
begin
  select -1 as result_code
  return
end


자주 저지르는 실수!

declare @result_code int , @processed_rows int

UPDATE DEPT SET DEPT_NM = '테스트부서' WHERE DEPT = 'AX'    -- 'AX'라는 부서는 존재하지 않는다고 가정. 이럴 경우 처리된 행의 개수는 0개임
 
set @processed_rows = @@rowcount
set @result_code = @@error

if @result_code <> 0 or @processed_rows <> 1
begin
  select @result_code
  return
end

위의 코드는 에러가 발생하면 @@error 와 @@rowcount 를 별도의 변수에 저장하고 에러를 처리하는 코드입니다. 그런데 위의 에러처리 루틴은 결코 실행되지 않습니다.  @result_code 를 세팅하기 전에 set @processed_rows = @@rowcount 가 성공하면서  @@error 가 0으로 되고 @result_code 에는 언제나 0 이 세팅되기 때문입니다.

그렇다면 코드를 이렇게 바꾸면 어떨까요?

declare @result_code int , @processed_rows int

UPDATE DEPT SET DEPT_NM = '테스트부서' WHERE DEPT = 'AX'  

set @result_code = @@error
set @processed_rows = @@rowcount

if @result_code <> 0 or @processed_rows <> 1
begin
  select @result_code
  return
end

update 문을 실행하자마자 @@error 를 @result_code 에 넣었으므로 정상적인 값이 들어갈 것입니다. 그러면 @@rowcount 는 어떨까요? DEPT 테이블에 AX라는 부서가 없으므로  @@rowcount 는 0 이 되어야 합니다. 하지만 실행시켜보면 @processed_rows 에 1 이 들어가 있습니다. 이게 어찌된 일일까요???

원인은 set @result_code = @@error 때문입니다. @@rowcount 는 set 문에 의해서도 영향을 받습니다. 따라서 set @result_code = @@error 가 성공하면 한 개의 데이터가 변수에 저장되었으므로 @@rowcount 는 1이 되는 것입니다.

(참고 : http://msdn2.microsoft.com/ko-kr/library/ms187316.aspx)

정확한 코드는 다음과 같습니다.

declare @result_code int , @processed_rows int

UPDATE DEPT SET DEPT_NM = '테스트부서' WHERE DEPT = 'AX'  

select @result_code = @@error , @processed_rows = @@rowcount

if @result_code <> 0 or @processed_rows <> 1
begin
  select @result_code
  return
end

select 문도 변수에 값을 저장할 수 있습니다. select 문을 이용해서 한꺼번에 값을 저장하면 정확하게 원하는 값이 저장됩니다. SQL Server 2000 은 C++ 이나 Java, C# 에서 제공되는 try ~ catch 구문을 제공하지 않는다. (2005에서는 제공합니다) 따라서 에러 발생의 소지가 있는 각 insert, delete, update 문 마다 위와 같은 에러 처리 루틴을 넣어야 합니다.

(참고 : set 문으로 변수를 저장하는 것 보다 select 로 저장하는 것이 더 느리다는 개발자의 경험사례 보고가 있었습니다. 반복 테스트가 필요하겠습니다. 테스트 후 결과를 올리도록 하겠습니다.)

2. rollback, commit 할 때는 언제나 @@trancount 를 체크하자

@@trancount : 트랜잭션의 중첩 수준을 나타내는 시스템 변수. Begin tran 문에 의해 1씩 증가하고 commit tran 에 의해 1씩 감소한다. rollback tran 을 만나면 모두 롤백하면서 어떤 값을 가지고 있더라도 0 으로 변한다.

sp를 작성할 때 데이터의 정합성을 보장하기 위해서 트랜잭션을 사용하게 됩니다. 트랜잭션을 시작하면 언제나 begin tran, commit tran의 짝이 일치해야 하는 것은 당연하지요. 즉, 트랜잭션이 중첩되어서 begin tran 을 세번하게 되면 세번 commit 이 있어야 합니다. 단 rollback 은 한번에 @@trancount 를 0 으로 만들고 rollback 하기 때문에 rollback 하기 전에 언제나 @@trancount 를 체크하면서 rollback 해야 합니다.

begin tran

INSERT INTO DEPT ( … )

if @@error <> 0 or @@rowcount <> 1
begin
  if @@trancount > 0 rollback
  select -1 as err_code
  return
end

INSERT INTO TEST_TBL ( … )

if @@error <> 0 or @@rowcount <> 1
begin
  if @@trancount > 0 rollback
  select -2 as err_code
  return
end

if @@trancount > 0 commit

rollback 이나 commit 하기 전에 @@trancount 를 체크하는 것은 sp들간에 복잡하게 호출하고 각 sp들이 자체적으로 transaction 을 사용할 때 위력을 발휘합니다. 중첩 트랜잭션 처리에 관한 사항은 기배포한 중첩 트랜잭션 처리 가이드를 참고해주세요.

Posted by maceo

08 1, 2006 07:16 08 1, 2006 07:16
, , ,
Response
No Trackback , 2 Comments
RSS :
http://merritt.co.kr/tt/rss/response/59

Extreme Programming Explained 2판 출간

익스트림 프로그래밍 - 변화를 포용하라, 2판  켄트 벡.신시아 안드레스 지음, 정지호.김창준 옮김
'Extreme Programming' 초판이 나오고 5년 만에 두 번째 판이 나왔다. 개정판이라고는 하지만 사실상 완전히 새로 쓴 것이나 다름없다. 2판은 '무엇'에서 한 단계 더 나아가 XP에 대한 '왜', 곧 실천방법 뒤에 놓인 동기와 원칙들에 대해 매우 많은 것을 말해준다.

나를 만든 책중의 하나인 Extreme Programming Explained 2판이 출간됐다.

때는 바야흐로 2002년, 좌충우돌 초보팀장 시절. 쉽지 않은 프로젝트 두개를 어떻게 관리해야할 지 막막하던 와중에 한줄기 빛이 되어준 김창준님의 XP 소개 기사. 기사를 읽자마자 XP 시리즈 책을 아마존에서 한꺼번에 구입, 순식간에 다 읽었다. 그야말로 제대로 꽂혀서 XP 신도가 되긴 했는데, 돌이켜보건데 철저한 XP 신도인 것만은 아니었던 것 같다.

가장 중요한 테스트 주도 개발을 스스로 관철시키지 못했다. 당시 이니시스에 다니던 후배말로는 습관바꾸는게 너무 힘들었는데 바꾸고 나니 확실히 좋긴 좋았다는 이야기를 들었을 뿐,정작 나는 습관을 바꾸진 못했다. 하지만 NUnit 이나 VBUnit 을 이용해서 테스트 코드를 만들고, 그것을 통과한 코드는 정말로 믿음이 갔다. 뭐랄까... 테스트를 통과한 코드에 문제가 있을리 없다는 자신감? 안도감? 뭐 그런 느낌이랄까? 그리고 변경에 대한 두려움이 확실히 줄어들긴 한다. 하지만 변경이 너무 잦은 경우 테스트 코드와 원래 로직을 함께 바꿔야 하는 부담이 있어서 그 고비를 넘지 못한게 못내 아쉽다. 그때 분명히 내가 잘못한게 있었을 것이다.

그리고 pair programming 도 완전하게 도입하진 못했다. 신입사원 교육할때나 개발 난이도가 좀 있어서 타인의 크로스 체킹이 필요할 때 정도만 pair programming 을 활용했던 것 같다. 다만, 활용해보면 그 효과는 정말로 끝내준다. 개발 속도가 그렇게 느리지도 않을 뿐더러 버그가 확실히 적어진다. 내가 회사 나간 후 클라이언트 개발을 pair 로 상당부분 진행했다고 하는데, 둘이 각자 진행하는것과 비교해서 진척률도 비슷하고 품질은 당연히 더 높았다고 하는군.

유저스토리나 계획게임, 가장 가치있는 것부터 만들기, 매일 10분 간단 미팅 등은 지금 회사에서 플젝 관리를 할 때도 유용하게 써먹는 best practice 다. 마침 울회사의 프로젝트란게 프로젝트다운 프로젝트는 없고 끊임없는 개선작업 정도라고 부르면 적당하다. 1~3명의 개발자가 2주~1달정도 하는 것이니 XP의 일부 practice 를 적용해보기에 아주 좋다. 상담서비스 개발할때 가장 가치있는 것부터 만들기, 매일 10분 간단 미팅 등을 적용해서 이슈거리는 미리미리 제거하고 프로젝트 진행의 가시성을 확보했으며 전체적으로 스무스하게 프로젝트를 끝낸 경험이 있다. 지금 하고 있는 알바에서도 가장 가치있는 것부터 만들기 practice 를 적용중이고...

그때나 지금이나 완전한 XP프로젝트는 겪어보지 못했고 이젠 DBA를 하는지라 불행히도 앞으로 겪어볼 일이 없을 것 같지만, 실제 업무에서 너무나 유용하게 쓰일 수 있는 지혜로 가득차 있는 방법론이라 할만한다. 그런 점에서 XP Explained 의 2판 출간이 너무나 반갑다. 이런책은 자비로 질러줘야 한다. ㅋㅋㅋ



@서점에 가보니 Refactoring to Patterns 번역본도 나와있고 실전에서 어쩌구 하는 패턴책도 있고... 4년전에 비해서 시장규모는 줄었지만 좋은 책은 정말 많이 나왔다. Enterprise Architecture Pattern 이 미국내에서 출판도 되기 전에 Martin Fowler 홈페이지에서 하나하나 받아서 프린트해가며 공부하던 시절이 엊그제 같은데 그책 번역판도 나와있고... 격세지감이 느껴지누만.

Posted by maceo

07 30, 2006 17:17 07 30, 2006 17:17
,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/58

« Previous : 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : Next »

블로그 이미지

가늘어도 긴놈이 장땡

- maceo

Archives

Authors

  1. maceo

Calendar

«   9 2010   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    

Site Stats

Total hits:
179781
Today:
28
Yesterday:
67