수안이의 컴퓨터 연구실

  • Mainpage
  • About Me
  • Tags
  • Metapage
  • Notice
  • Location
  • Keywords
  • Guestbook
  • Admin
  • Write an Article
  • Total | 1693968
  • Today | 319
  • Yesterday | 588

1 Articles, Search for '확장 update'

  1. 2007/05/21 SQL Server 2000에서 update시 join의 활용
Database/MSSQL2007/05/21 09:28

SQL Server 2000에서 update시 join의 활용

update나 delete시에도 select의 경우와 마찬가지로 원하는 대상집합을 정의하기 위해서 여러 테이블을 join할 수 있다. 대용량 데이터베이스 솔루션 2권에서는 이에 대해서 '확장 update문'이라는 형태로 설명하고 있다.

오라클과 SQL Server 2000 모두 이러한 형태의 SQL을 지원하지만, 문법의 차이가 상당하므로 이 둘의 차이점에 대해서 설명하고자 한다.



우선, update시 SQL문의 차이점에 대해서 알아보자.

2004년 2월에 가입한 고객에 대해서, 총주문회수와 총주문금액을 주문 테이블로부터 계산해서 고객 테이블에 반영하고자 한다.

< 오라클 9.2.0 >



실행결과는 다음과 같다.

Rows Row Source Operation
---------- ---------------------------------------------------
0 UPDATE
2 TABLE ACCESS BY INDEX ROWID 고객
2 INDEX RANGE SCAN 고객_IDX1 (고객_IDX1)
2 SORT AGGREGATE
2 TABLE ACCESS BY INDEX ROWID 주문
2 INDEX RANGE SCAN 주문_IDX1 (주문_IDX1)


고객 고객명 가입일자 총주문회수 총주문금액
----- -------------------- -------- ---------- ----------
00001 홍길동 20040101 0 0
00002 이순신 20040201 2 80000
00003 강감찬 20040201 0 0


< SQL Server 2000 >

SQL Server 2000에서는 set (col1, col2) = (값1, 값2) 형태의 구문이 지원되지 않는다. 또한, 'update table a'와 같이 테이블에 alias를 적용할 수도 없으므로 오라클과는 다른 형태의 SQL을 사용해야 한다.

[SQL #1]


실행결과는 다음과 같다.

(1개 행 적용됨)

'고객' 테이블. 스캔 수 1, 논리적 읽기 수 4, 물리적 읽기 수 0, 미리 읽기 수 0.
'주문' 테이블. 스캔 수 1, 논리적 읽기 수 5, 물리적 읽기 수 0, 미리 읽기 수 0.


Rows Executes StmtText
------------------------------------------------------------------------------
1 1 |--Table Update(OBJECT:([encore].[dbo].[고객]), SET:([고객].[총주문금액]=[Expr1006], [고객].[총주문회수]=[Expr1001]))
1 1 |--Compute Scalar(DEFINE:([Expr1006]=Convert([Expr1002])))
1 1 |--Top(ROWCOUNT est 0)
1 1 |--Merge Join(Inner Join, MERGE:([a].[고객번호])=([b].[고객번호]), RESIDUAL:([a].[고객번호]=[b].[고객번호]))
2 1 |--Sort(ORDER BY:([a].[고객번호] ASC))
2 1 | |--Bookmark Lookup(BOOKMARK:([Bmk1003]), OBJECT:([encore].[dbo].[고객] AS [a]))
2 1 | |--Index Seek(OBJECT:([encore].[dbo].[고객].[고객_idx1] AS [a]), SEEK:([a].[가입일자] >= '200402' AND [a].[가입일자] < '200403'), WHERE:(like([a].[가입일자], '200402%', NULL)) ORDERED FORWARD)
2 1 |--Compute Scalar(DEFINE:([Expr1001]=Convert([Expr1013]), [Expr1002]=If ([Expr1014]=0) then NULL else [Expr1015]))
2 1 |--Stream Aggregate(GROUP BY:([b].[고객번호]) DEFINE:([Expr1013]=Count(*), [Expr1014]=COUNT_BIG([b].[주문금액]), [Expr1015]=SUM([b].[주문금액])))
4 1 |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([encore].[dbo].[주문] AS [b]))
4 1 |--Index Scan(OBJECT:([encore].[dbo].[주문].[주문_idx1] AS [b]), ORDERED FORWARD)


고객번호 고객명 가입일자 총주문회수 총주문금액
------------------------------------------------------------------
00001 홍길동 20040101 0 0
00002 이순신 20040201 2 80000
00003 강감찬 20040201 0 0

(3개 행 적용됨)

또는, 다음과 같은 SQL도 가능하다.

[SQL #2]


(1개 행 적용됨)

'고객' 테이블. 스캔 수 2, 논리적 읽기 수 5, 물리적 읽기 수 0, 미리 읽기 수 0.
'Worktable' 테이블. 스캔 수 1, 논리적 읽기 수 3, 물리적 읽기 수 0, 미리 읽기 수 0.
'주문' 테이블. 스캔 수 2, 논리적 읽기 수 4, 물리적 읽기 수 0, 미리 읽기 수 0.


Rows Executes StmtText
------------------------------------------------------------------------------
1 1 |--Table Update(OBJECT:([encore].[dbo].[고객]), SET:([고객].[총주문금액]=[Expr1008], [고객].[총주문회수]=[Expr1002]))
1 1 |--Table Spool
1 1 |--Compute Scalar(DEFINE:([Expr1008]=Convert([Expr1003])))
1 1 |--Top(ROWCOUNT est 0)
1 1 |--Nested Loops(Inner Join, OUTER REFERENCES:([b].[고객번호]))
1 1 |--Compute Scalar(DEFINE:([Expr1002]=Convert([Expr1009]), [Expr1003]=If ([Expr1010]=0) then NULL else [Expr1011]))
1 1 | |--Stream Aggregate(GROUP BY:([b].[고객번호]) DEFINE:([Expr1009]=Count(*), [Expr1010]=COUNT_BIG([b].[주문금액]), [Expr1011]=SUM([b].[주문금액])))
2 1 | |--Bookmark Lookup(BOOKMARK:([Bmk1001]), OBJECT:([encore].[dbo].[주문] AS [b]))
2 1 | |--Nested Loops(Inner Join, OUTER REFERENCES:([a].[고객번호]))
2 1 | |--Sort(ORDER BY:([a].[고객번호] ASC))
2 1 | | |--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([encore].[dbo].[고객] AS [a]))
2 1 | | |--Index Seek(OBJECT:([encore].[dbo].[고객].[고객_idx1] AS [a]), SEEK:([a].[가입일자] >= '200402' AND [a].[가입일자] < '200403'), WHERE:(like([a].[가입일자], '200402%', NULL)) ORDERED FORWARD)
2 2 | |--Index Seek(OBJECT:([encore].[dbo].[주문].[주문_idx1] AS [b]), SEEK:([b].[고객번호]=[a].[고객번호]) ORDERED FORWARD)
1 1 |--Index Seek(OBJECT:([encore].[dbo].[고객].[고객_pk]), SEEK:([고객].[고객번호]=[b].[고객번호]) ORDERED FORWARD)


고객번호 고객명 가입일자 총주문회수 총주문금액
------------------------------------------------------------------
00001 홍길동 20040101 0 0
00002 이순신 20040201 2 80000
00003 강감찬 20040201 0 0

(3개 행 적용됨)

첫 번째 SQL과 두 번째 SQL의 실행계획의 차이점은 다음과 같다.

첫 번째 SQL은 [주문_idx1] 인덱스를 Index Scan 했지만 고객 테이블은 단 1번만 액세스했다. 이 경우, 주문 테이블의 데이터량이 많지만 조건에 해당하는 고객이 적으면 불필요한 인덱스 페이지를 모두 스캔해야 하므로 비효율이 발생할 수 있다.

두 번째 SQL은 [주문_idx1] 인덱스를 Index Seek 했지만 고객 테이블을 두 번 액세스했다. 이 경우, 액세스 회수는 2번이지만 논리적 읽기 수는 첫 번째 SQL과 동일하므로 비효율이 발생했다고 보기는 어렵다.

주문 테이블의 데이터량이 많고 대부분의 데이터가 조건에 해당된다면, 첫 번째 SQL의 실행계획이 더 효율적일 수도 있다.

각 테이블의 데이터 분포 정도에 따라서 가장 효율적인 실행계획이 나오도록 적절한 형태의 SQL을 사용하면 된다.

* Index Scan : 인덱스에서 모든 행을 검색한다.
오라클에서의 index full scan과 유사
* Index Seek : [SEEK:()] 조건자에 부합되는 행만 처리한다.
오라클에서의 index unique scan 또는 index range scan과 유사
* 참고로 다음과 같이 SQL을 작성하면 구문 오류가 발생한다.



집계는 UPDATE 문의 SET 목록에 나타나지 않습니다.

출처 : 엔코아 정보 컨설팅
"MSSQL" 카테고리의 다른 글
  • SQL Server 2000에서 varchar와 char 데이터 타입 (0)2007/05/21
  • SQL 서버 2005 보안 (0)2007/05/21
  • 새로운 SQL 서버 로그인 생성하기 (0)2007/05/21
  • SQL Server 2000에서 update시 join의 활용 (0)2007/05/21
  • Inside SQL Server Tip 갤러리 (0)2007/05/21
2007/05/21 09:28 2007/05/21 09:28
Posted by webdizen
Tags join, SQL Server, 확장 update
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/3002

Leave your greetings.

[로그인][오픈아이디란?]

«Prev  1  Next»

RSS HanRSS
Blog Image
webdizen
이곳은 컴퓨터에 대해 연구하고, 공유하고, 소통하기 위한 연구실입니다. 개인적으로는 OLAP, Data Mining, Semantic Web, Data Modeling에 대해서 연구하고 있습니다.

Categories

전체 (3009)
Webdizen (141)
Life (6)
Diary (16)
Blog (9)
IDEA (2)
Travel (10)
Book (16)
Photo (7)
Movie (8)
Music (14)
Leisure Sports (10)
Funny (6)
Hardware (121)
Software (120)
Windows (5)
Unix & Linux (120)
Installation (5)
Kernel (10)
System (34)
Develop (22)
X-Window (0)
Applicaton (31)
Security (4)
Framework (2)
Hadoop (2)
Programming (804)
Algorithm & Data Structure (1)
Assembly (38)
UNIX/Linux C (95)
C++ (128)
STL (4)
Java (38)
Win32 API (92)
ATL/COM (44)
MFC (151)
.NET (26)
WCF/WPF (4)
C# (28)
Network Programming (17)
Database Programming (12)
OpenGL / DirectX (13)
Multimedia Programming (0)
Game Programming (21)
Parallel Distributed Progra... (0)
Reverse Engineering (0)
Debugging (9)
Python (1)
Ruby (1)
Ruby on Rails (1)
QT (4)
GTK (0)
JSP (0)
PHP (6)
ASP.NET (6)
ASP (2)
Development (28)
Useful Library (2)
Data Modeling (0)
Database (105)
Oracle (4)
MSSQL (41)
MySQL (2)
Data Warehouse (2)
Data Mining (4)
Network (66)
Web (79)
DHTML (4)
XHTML (1)
Javascript (1)
CSS (1)
AJAX (9)
XML (11)
Flex (1)
Silverlight (3)
Security (91)
DoS (1)
Kernel (10)
Scanning (3)
Sniffing (0)
Spoofing (4)
Overflow (28)
Web (11)
Shell (10)
Format String (14)
Window (2)
Embedded (70)
Multimedia (27)
Mobile (14)
Graphic (24)
Management (633)
Knowledge (581)
Hadoop (0)

Notice

  • 메타 블로그 사이트에 등록
  • 새해 맞이 블로그의 변화
  • 블로그 명칭 변경
  • 도메인(www.webdizen.net) 구...
  • TEXTCUBE 1.6.1로 업그레이드...

Tags

  • 컨테이너
  • DOCTYPE
  • Chat
  • 학습
  • Web2.0
  • DOM
  • 객체지향
  • Bitmap ImageList
  • C#
  • 제1기숙사
  • SOA Engagement
  • tty
  • Google
  • 시스템 관리
  • 음악
  • 삼성
  • Game
  • 20가지 법칙
  • SUID
  • proc

Recent Articles

  • 트위터(Twitter)의 시작!.
  • 청년 리더의 조건.
  • 애플의 타블렛 PC - 아이패드....
  • 미래의 인터페이스 - 육감 기....
  • 기초발성법 동영상 강좌.

Recent Comments

  • 학교 과제물중 쓰레드에 대하....
    장진혁 03/17
  • 관리자만 볼 수 있는 댓글입....
    비밀방문자 03/12
  • 상대방의 이야기를 열심히 경....
    DoNuts 03/03
  • Lots of students know techn....
    Bobbi35Shannon 02/25
  • 좋은글 잘 보고 갑니다..
    Und_hacker 01/08

Recent Trackbacks

  • printf,scanf를 이용한 형식....
    yundream의 프로그래밍 이야기 03/10
  • 파일 열기/저장하기 CFileDialog.
    은마군의 나태블록 2009
  • World IT Show 2008.
    상우 :: Oranzie's BLOG 2008
  • cvs서버 설치하기.
    3인3색 2008
  • 속속 공개되는 Google Chart....
    PHP와 Web 2.0 2007

Archive

  • 2010/02 (1)
  • 2010/01 (6)
  • 2009/12 (5)
  • 2009/09 (3)
  • 2009/08 (1)

Calendar

«   2010/03   »
일 월 화 수 목 금 토
  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 31      

Bookmarks

    • Administration
      • IIS.NET
      • NTFAQ
      • OS의 모든 것
      • 리눅스포털
    • Database
      • SQL Server Central
      • SQL Team
    • Development
      • .NET Heaven
      • ASP Alliance
      • ASP.NET 2.0
      • Bullog.net
      • C# Corner
      • C++ (C PlusPlus.com)
      • C++ Reference
      • CodeGuru
      • CodePlex
      • DebugLab
      • Dev Articles
      • Devpia
      • DotNet Junkies
      • DotNet Zone
      • Driver Online
      • GOSU.NET
      • HOONS 닷넷
      • Joinc 팀블로그
      • KOSR
      • MSDN Home Page
      • OSR Online
      • Sky.ph - 개발자 커뮤니...
      • TAEYO.NET
      • The Code Project
      • WindowsClient.net
      • 김상욱의 개발자 Side
      • 조인시 위키
    • Human Networks
      • belief21c's e-space
      • I think I can
      • Invisible Rover's Blog :D
      • Rodman®
      • ■ Feel So Good~! ■
      • 까만 나비
      • 나를 가꾸는 시간.
      • 나만의 즐거움~~!
      • 단녕
      • 상우 :: Oranzie's BLOG
    • Information Technology
      • Microsoft TechNet
      • 지디넷코리아 - 글로벌...
    • Security
      • FoundStone
      • milw0rm
      • NewOrder
      • OpenRCE
      • Phrack.org
      • Reverse Engineering b1...
      • Reverse Engineering Team
      • RootKit
      • SecurityFocus
      • SecurityXploded by Nag...
      • Wow Hacker
      • Zone-H
Textcube
Louice Studio Inc.
Powered by Textcube. Original designed by Tistory.