SQL은 반듯이 데이터 변경에 따른 기록을 우선 로그 파일에 기록을 하게 됩니다.(Write Ahead Logging)
그리고 이러한 로그는 트랜잭션 롤백 또는 롤 포워드시에 사용하게 됩니다.

이러한 로깅으로 인해서 많은 데이터 변경 작업시 로그파일에 많은 IO가 발생하여, 전체적인 성능에 영향을 줄 수 있습니다.
그렇다면 굳이 로깅을 하지 않아도 되는 새로운 테이블에 데이터 추가 등에 대해서 최소로깅으로 처리한다면 보다 좋은 성능을 가질 수 있을것입니다.

최소 로깅이란 굳이 모든 데이터에 대해서 로깅할 필요가 없는 작업에 대해서 모든 데이터에 대해서 로깅을 하는 것이 아닌 할당 정보등에 대해서만 로깅을 하는 것입니다.
최소 로깅은 SIMPLE, BULK LOGGED 복구 모델에서만 할 수 있습니다.
보다 자세한 내용은 온라인 설명서로~

이러한 최소 로깅은 OLTP의 배치성 작업 또는 DW의 ETL에서 사용하는 것이 보통입니다. 최소 로깅을 사용하기 위해서는 SELECT INTO 또는 DTS, SSIS, BCP, BULK INSERT를 활용할 수 밖에 없었습니다.

하지만 SQL Server 2008에서는 INSERT구문에 대해서도 최소 로깅을 지원합니다.
로깅을 하지 않기 위해서는 row단위의 로깅 데이터가 없어도 롤백을 할 수 있어야 하기에 어쩔수 없이 여러가지 제약 사항은 있습니다.

  1. TABLOCK힌트 반듯이 추가
  2. 클러스터 인덱스만 존재하고, 비어있는 테이블 또는 어떠한 인덱스도 없는, 비어있지 않은 테이블

송 혁, SQL Server MVP
sqler.pe.kr
nexondbteam.tistory.com

USE MASTER

GO

DROP DATABASE TEST1

GO

CREATE DATABASE TEST1

GO

ALTER DATABASE TEST1 SET RECOVERY BULK_LOGGED

 

USE TEST1

GO

--========================================================[클러스터인덱스만있는빈테이블]

CREATE TABLE tbl9(a int not null, b char(4000))

CREATE UNIQUE CLUSTERED INDEX cl_tbl9 on tbl9 ( a )

 

DECLARE @CurrentLSN varchar(23)

SELECT @CurrentLSN = [Current LSN] FROM fn_dblog(null,null) ORDER BY [Current LSN] DESC

 

INSERT INTO tbl9

select  TOP 10000

       row_number() over(order by a.id) as col1

       , 'Hyoksong' as col2

FROM sys.sysindexes A , sys.sysindexes B

 

SELECT SUM([Log Record Length]) FROM fn_dblog(null,null)

WHERE[Current LSN] > @CurrentLSN

--=SUM([Log Record Length]) = 44261980

 

/*

 -- TABLOCK hint

*/

 

CREATE TABLE tbl10(a int not null, b char(4000))

CREATE UNIQUE CLUSTERED INDEX cl_tbl10 on tbl10 ( a )

 

DECLARE @CurrentLSN varchar(23)

SELECT @CurrentLSN = [Current LSN] FROM fn_dblog(null,null) ORDER BY [Current LSN] DESC

 

INSERT INTO tbl10 WITH(TABLOCK)

select  TOP 10000

       row_number() over(order by a.id) as col1

       , 'Hyoksong' as col2

FROM sys.sysindexes A , sys.sysindexes B

 

SELECT SUM([Log Record Length]) FROM fn_dblog(null,null)

WHERE[Current LSN] > @CurrentLSN

--=SUM([Log Record Length]) = 386876

 

--========================================================[힙이며인덱스가없는비어있지않은테이블]

CREATE TABLE tbl11(a int not null, b char(4000))

 

INSERT INTO tbl11

select  TOP 100

       row_number() over(order by a.id) as col1

       , 'Hyoksong' as col2

FROM sys.sysindexes A , sys.sysindexes B

GO

 

DECLARE @CurrentLSN varchar(23)

SELECT @CurrentLSN = [Current LSN] FROM fn_dblog(null,null) ORDER BY [Current LSN] DESC

 

INSERT INTO tbl11

select  TOP 10000

       row_number() over(order by a.id) as col1

       , 'Hyoksong' as col2

FROM sys.sysindexes A , sys.sysindexes B

 

SELECT SUM([Log Record Length]) FROM fn_dblog(null,null)

WHERE[Current LSN]>@CurrentLSN

--=SUM([Log Record Length]) = 87101448

 

/*

 -- TABLOCK hint

*/

CREATE TABLE tbl12(a int not null, b char(4000))

 

INSERT INTO tbl12

select  TOP 100

       row_number() over(order by a.id) as col1

       , 'Hyoksong' as col2

FROM sys.sysindexes A , sys.sysindexes B

GO

 

DECLARE @CurrentLSN varchar(23)

SELECT @CurrentLSN = [Current LSN] FROM fn_dblog(null,null) ORDER BY [Current LSN] DESC

 

INSERT INTO tbl12 WITH(TABLOCK)

select  TOP 10000

       row_number() over(order by a.id) as col1

       , 'Hyoksong' as col2

FROM sys.sysindexes A , sys.sysindexes B

 

SELECT SUM([Log Record Length]) FROM fn_dblog(null,null)

WHERE[Current LSN]>@CurrentLSN

--=SUM([Log Record Length]) = 929276

신고
Posted by 송혁 - HyokSong

SQL Server 2005의 SQLWB는 이전 2000에서 사용하는 기능이 없어져 많이 불편하였습니다.

하지만 2008에서는 2000의 QA기능을 많은 기능을 가져온 듯하며, 기존의 좋은 기능뿐만 아니라 IntelliSense기능을 지원하여 보다 간편하게 T-SQL을 작성할 수 있습니다.
(아직까지 좋은지는 잘 모르겠지만.)

그리고 오류 목록 창이라는 것이 추가 되었습니다.
작성 중인 T-SQL의 구문 오류에 대해서 보여주는 창입니다.
긴 T-SQL 구문에서 오류가 발생할 경우 유용하게 사용할 수 있을 것 같습니다.

<SSMS 오류 목록 메뉴>

<오류 목록 창>  

사용자 삽입 이미지


아래는 BOL에 있는 내용~
오류 목록의 기능

  1. 오류 목록은 다음 기능을 제공합니다.
  2. 스크립트를 편집할 때 오류 목록은 Transact-SQL 쿼리 편집기의 IntelliSense에 의해 생성되는 오류 및 경고를 표시합니다.
  3. 오류 메시지 항목을 두 번 클릭하여 오류를 생성한 스크립트 파일의 탭에 포커스를 두고 오류 위치로 이동할 수 있습니다.
  4. 표시되는 항목 및 각 항목에 대해 표시되는 정보 열을 필터링할 수 있습니다.
  5. 오류를 수정하면 해당 오류 항목이 오류 목록에서 제거됩니다.
  6. Transact-SQL 스크립트 파일 탭을 닫으면 해당 파일에 대한 오류가 오류 목록에서 제거됩니다.

보다 자세한 내용은 SQL Server 2008 CTP6 BOL을 참조 하세요.
ms-help://MS.SQLCC.v10/MS.SQLSVR.v10.Ko/s10de_5techref/html/fae6327d-e268-44ae-a474-4a8f8f843129.htm

송 혁, SQL Server MVP
sqler.pe.kr
nexondbteam.tistory.com

신고
Posted by 송혁 - HyokSong

Heap인 테이블의 가변형 데이터 타입에 보다 큰 데이터로 변경하게 되면 클러스터 인덱스와 같은 페이지 분할이 아닌, 다른 곳으로 저장 후 포인터를 가지고 있는 Forward Pointer가 생기게 됩니다.

이로 인해서 적은 데이터를 읽을경우에도 포인터로 추가 컬럼에 대한 데이터도 엑세스 하는경우에는 성능에 문제가 있었습니다.

현재 운영중인 환경에서 얼마나 많은 Forward Pointer를 사용하여 데이터를 엑세스를 하는지 확인 하는 방법은 성능모니터에서 "SQL Server:Access Methods // Forwarded Records/sec" 의 값을 추가하여 확인할 수 있습니다.

이러한 Forward Pointer를 제거 하기 위해서는 SQL Server 2008이전에는 클러스터 인덱스를 만들거나, 다른 테이블로 데이터를 일괄 입력 후 이름 변경하여 처리하는 방법 밖에는 없었습니다.

여기서 "클러스터 인덱스의 페이지 분할, Heap의 Forward Pointer에 대해 어떤게 더 좋아?~" 를 이야기를 하는 것은 아닙니다.
단지 말하고 싶은 것은 "SQL Server 2008에서는 heap인 테이블에 대해서도 REBUILD를 지원해 준다.!!" 입니다.

아래는 CTP6에서 테스트한 내용입니다.
Microsoft SQL Server code name "Katmai" (CTP) - 10.0.1300.13 (Intel X86)
    Feb 8 2008 00:06:52
    Copyright (c) 1988-2007 Microsoft Corporation
    Developer Edition on Windows NT 5.2 <X86> (Build 3790: Service Pack 2)

USE
TEST
GO
DROP TABLE tbl1

-- 샘플 테이블을 만들자.
SELECT TOP 10000
ROW_NUMBER() over(order by A.id) col1
,cast('HS' as varchar(1000))col2
INTO tbl1
FROM sys.sysindexes A, sys.sysindexes B,sys.sysindexes C,sys.sysindexes D,sys.sysindexes E

-- forwarded_record 및 조각화 상태를 보자.
SELECT 
    INDEX_TYPE_DESC
   ,FRAGMENT_COUNT
   ,PAGE_COUNT
   ,FORWARDED_RECORD_COUNT
FROM SYS.DM_DB_INDEX_PHYSICAL_STATS(DB_ID(),DEFAULT,DEFAULT,DEFAULT,'DETAILED')
WHERE OBJECT_ID = OBJECT_ID('tbl1') /*

index_type_desc fragment_count page_count forwarded_record_count

------------------------------------------------------------ ------------HEAP                            2                       30                      0

*/

--80바이트로 업데이트를 하자

UPDATE tbl1 WITH(TABLOCKX)

set col2 = replicate('HyokSong',10)


/*

index_type_desc fragment_count page_count forwarded_record_count

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

HEAP                               8                155                      8689

*/

--

ALTER TABLE tbl1 REBUILD

/*

index_type_desc fragment_count page_count forwarded_record_count

------------------------------------------------------------ ------------HEAP                                    2            126                  0

*/

송 혁, SQL Server MVP
sqler.pe.kr
nexondbteam.tistory.com

신고
Posted by 송혁 - HyokSong

SQL Server 2005부터 OUTPUT절이 추가 되어 UPDATE, INSERT, DELETE 작업에 대한 대상 행을 테이블 변수로 저장하여 활용할 수 있었습니다.

하지만 대상 데이터를 다른 테이블에 저장하기 위해서는 테이블 변수로 저장 후 다시 저장해야 하는 번거로움이 있었습니다.


이러한 문제에 대해서 몇 가지 제한 사항이 존재 하지만 SQL Server 2008은 OUTPUT절을 포함하는 UPDATE, INSERT, DELETE, MERGE의 OUTPUT결과를 하나의 구문으로 다른 테이블에

저장할 수 있는 기능을 제공하고 있습니다.


해당 기능은 CTP5부터 지원되며, 보다 자세한 내용은 SQL Server 2008 BOL에서 INSERT 부분을 참고하세요.

use tempdb

go

--drop table tblSource

--drop table tblTarget

create table tblSource(col1 int)

create table tblTarget(col1 int)


--delete tblSource

--delete tblTarget

insert into tblSource values(1),(2),(3),(4),(5),(6)


--INSERT

insert into tblTarget(col1)

select col1

from (insert into tblSource output inserted.col1 values(10),(11),(12) ) as d;


--UPDATE

insert into tblTarget(col1)

select col1

from (update tblSource set col1 = col1 + 1 output deleted.col1) as d;


--DELETE

insert into tblTarget(col1)

select col1 from (delete tblSource output deleted.col1 where col1%2 = 0)X

송 혁, SQL Server MVP

sqler.pe.kr

nexondbteam.tistory.com

신고
Posted by 송혁 - HyokSong


티스토리 툴바