'2019/03'에 해당되는 글 4건

Programming/Microsoft SQL Server

1. 인덱스 생성

 

인덱스를 생성하기전 우선 간단한 형태의 테이블을 만들어 보겠습니다.

 

Create Table Items (
    item_no Int,
    item_name nChar(10),
    item_price Decimal(8, 2),
    item_description nVarChar(500)
);

 

인덱스는 다음과 같은 방법으로 생성합니다.

 

Create Clustered Index item_no_idx
On Items (item_no);

 

위 구문은 Items 테이블의 item_no 열에 대해 Clustered 형 인덱스를 생성하도록 합니다. Create 구문에서 Clustered 를 생략하면 기본값인 Nonclustered 인덱스가 생성되며 Unique 를 지정하면 중복값이 없는 인덱스를 생성합니다. 기본값은 중복가능입니다.

 

만약 인덱스를 지정할 열(Column)이 2개 이상이라면 콤마(,)를 통해 열을 구분하면 됩니다.

 

Create NonClustered Index item_no_idx
On Items (item_no, item_name);

 

데이터의 정렬순서를 지정하려면 열(Column)뒤에 Asc나 Desc를 지정하면 됩니다. 기본값은 Asc입니다.

 

Create Clustered Index item_no_idx
On Items (item_no Desc);

 

생성 구문 하위에 다시 On을 지정하여 인덱스를 별도의 파일그룹에 생성할 수 있습니다. 인덱스를 타는 경우 인덱스 테이블과 데이터 테이블에 거의 동시에 접근이 시도되므로 데이터 테이블이 존재하는 디스크 이외에 다른 디스크에 파일그룹을 생성하고 해당 파일그룹에 인덱스를 생성하면 성능상 이점을 얻을 수 있게 됩니다.

 

 

Subgroup이라는 별도의 파일 그룹을 생성합니다.

 

 

새로운 파일을 생성하고 해당 파일에 대한 파일그룹을 위에서 만든 Subgroup에 지정합니다. 이때 해당 파일을 별도의 디스크에 생성하도록 하면 인덱스 테이블과 데이터 테이블을 분리할 수 있게 됩니다.

 

위와 같이 파일 그룹을 생성하고

 

Create Clustered Index item_no_idx
On Items (item_no Desc)
On Subgroup;

 

해당 파일 그룹에 인덱스를 생성하면 분리가 완료됩니다.

 

인덱스를 생성하면 B-Tree구조로 인덱스 페이지가 만들어집니다. 페이지에 데이터가 채워지면 페이지가 다 채워지는 경우 새로운 페이지를 생성하여 데이터를 나누는 페이지 분할이 발생합니다. 해당 테이블이 자주 변경되는 경우라면 페이지 분할도 그만큼 자주 발생하게 되는데 이때 페이지에 데이터가 채워지는 기준을 정해주면 페이지 분할에 발생하는 부하를 조금이나마 감소시켜 줄 수 있습니다.

 

Create Clustered Index item_no_idx
On Items (item_no)
With (PAD_INDEX = On, Fillfactor = 50);

 

PAD_INDEX 옵션을 On으로 설정하고 Fillfactor에 50을 지정하면 인덱스를 생성할때 여유공간 50%를 확보하고 페이지를 생성하도록 합니다. 여유공간이 크면 클 수록 인덱스 페이지는 더 많은 데이터를 담을 수 있기에 페이지 분할횟수는 그 만큼 감소할 수 있습니다.

 

그러나 단점도 존재하는데 우선 여유공간을 많이 확보하면 할 수록 디스크 공간을 더 많이 차지하게 됩니다. 게다가 기존에 인덱스로 구성할 데이터가 많은 경우라면 페이지를 생성할때 여유공간을 확보하기 위해 기존보다 더 많은 페이지를 생성해야 하므로 일반적인 경우보다 검색속도는 느려질 수 있습니다.

 

tempdb가 별도의 디스크에 존재하는 경우 인덱스를 생성할때 다음과 같이 임시파일을 tempdb에 생성하도록 지정하면 인덱스 생성시에 성능을 더 높일 수 있습니다.

 

Create Clustered Index item_no_idx
On Items (item_no)
With (SORT_IN_TEMPDB = On);

 

특정 테이블에 대해 인덱스를 생성하면 인덱스 생성완료시까지 해당 테이블은 잠김상태가 됩니다. 필요하다면 Online 옵션을 지정해 인덱스 생성시에도 데이터 테이블에 접근이 가능하도록 할 수 있습니다.

 

Create Clustered Index item_no_idx
On Items (item_no)
With (Online = On);

 

인덱스를 생성할때 조금이라도 성능을 높이기 위해서 해당 서버의 CPU갯수를 최대한 확보하도록 할 수 있습니다.

 

Create Clustered Index item_no_idx
On Items (item_no)
With (Maxdop = 64);

 

위 예제는 64개의 CPU를 사용하도록 한 것인데 이것이 최대값입니다. 기본값은 0이며 이것은 시스템이 알아서 판단하도록 합니다.

 

인덱스는 생성시에 압축을 수행하여 디스크 공간을 절약하도록 할 수 있습니다.

 

Create Clustered Index item_no_idx
On Items (item_no)
With (Data_compression = Page);

 

Data_compression에 page를 지정하면 Page단위로 압축을 수행합니다. 반면 값을 Row로 하여 테이블의 Row단위로 압축할 수 있도록 지정할 수 있습니다.

 

 

 

2. 인덱스 변경

 

인덱스 변경에는 Alter Index 구문을 사용해 변경할 인덱스를 지정하고 On으로 테이블을 명시합니다.

 

Alter Index item_no_idx
On Items
Rebuild;

 

참고로 특정 인덱스가 아닌 테이블에 있는 모든 인덱스를 명시하고자 하는 경우에는 인덱스명대신 All 키워드를 사용합니다.

 

Alter Index ALL
On Items
Reorganize;

 

Rebuild 옵션은 기존 인덱스를 삭제하고 새로 생성하도록 합니다. 다만 해당 작업이 종료될때까지 테이블은 잠기게 되는데 With (Online=On) 옵션을 추가하면 계속 테이블을 사용할 수 있습니다.

 

Alter Index item_no_idx
On Items
Rebuild
With (Online = On);

 

아래 구문은 인덱스를 다시 구성하도록 합니다.

 

Alter Index item_no_idx
On Items
Reorganize;

 

이게 필요한 경우는 인덱스가 단편화된것을 모으기 위한 것입니다.

 

Select A.index_id, A.avg_fragmentation_in_percent
From sys.dm_db_index_physical_stats (DB_ID(), OBJECT_ID('dbo.items'), Null, Null, Null) As A Inner Join sys.indexes As B
On A.object_id = B.object_id
And A.index_id = B.index_id;

 

위 쿼리는 특정 테이블의 인덱스에 대해 단편화 정도를 확인할 수 있도록 합니다. avg_fragmentation_in_percent 열의 값이 단편화인데 예를 들어 이 값이 30이라면 30%정도의 단편화를 보이고 있다는 뜻입니다.

 

이 단편화 수치가 높으면 Alter Index 구문의 Reorganize 옵션으로 단편화를 줄여줄 수 있습니다.

 

3. 인덱스 삭제

 

인덱스를 삭제하고자 하는 경우 Drop Index 구문을 사용합니다.

 

Drop Index [dbo].[items].item_no_idx;

 

다만 Primary Key나 Unique제약조건을 통해 생성된 인덱스는 Drop Index로 삭제가 불가능하고 Alter Table을 수정해 제약조건을 우선 제거해야 합니다. 그러면 자연스럽게 인덱스도 삭제될 것입니다.

 

인덱스를 삭제할때 클러스터형과 비클러스터형 모두를 삭제하고자 하는 경우 되로록이면 비클러스터형을 우선 삭제하고 그 다음 클러스터형 순으로 삭제하는 것이 좋습니다. 클러스터형을 먼저 삭제하게 되면 클러스터형의 인덱스 페이지를 바라보던 비클러스터형의 리프 페이지들은 기존처럼 정보가 '페이지번호+고유번호'형태로 수정되어야 하는데 이 절차는 어차피 비클러스터형도 삭제할 거라면 거쳐야할 필요가 없기 때문입니다.

 

4. 인덱스 확인

 

생성된 인덱스를 정보를 확인해 보려면 sp_helpIndex 프로시저를 호출합니다.

 

Exec sp_helpIndex [items];

 

인덱스의 페이지수나 용량등 좀더 상세한 정보를 확인하려면 아래 쿼리를 수행하도록 합니다.

 

Select A.name, A.type_desc, C.data_pages, C.data_pages * 8 As 'kb'
From sys.indexes As A Inner Join sys.partitions As B
On A.object_id = B.object_id
And OBJECT_ID('dbo.items') = A.object_id
And A.index_id = B.index_id Inner JoIN sys.allocation_units As C
On C.container_id = B.hobt_id;

 

'Programming > Microsoft SQL Server' 카테고리의 다른 글

파일그룹에 인덱스생성 후 삭제관련 문제  (0) 2019.05.17
인덱스(Index) - 1  (0) 2019.03.26
[SQL] 전체 텍스트 검색  (0) 2018.09.27
트랜잭션 (Transaction)  (0) 2018.09.12
분산 트랜잭션 설정  (0) 2018.07.11
[SQL] 기본언어확인및 변경  (0) 2018.01.30
0 0
Programming/.NET

params는 메서드에 전달할 매개변수가 너무 많거나 몇개가 될지 예측할 수 없는 경우에 유용하게 사용될 수 있습니다.

 

static void Main()
{
     Console.WriteLine("return : {0}", plus(10, 20));
}

private static int plus(int a, int b)
{
     return a + b;
}

 

위 예제에서 현재 plus 메서드는 int형 매개변수 2개를 받도록 되어 있지만 더 많은 대상을 처리하려고 하는 경우

 

private static int plus(int a, int b, , int c, , int d, , int e, , int f....)
{
     return a + b + c + d + e + f....;
}

 

이런 형태로 계속해서 매개변수를 늘리는것은 효휼적이지 못할 것입니다.

 

private static int plus(params int[] num)
{
     int result = 0;

     for (int i = 0; i < num.Length; i++)
          result += num[i];

     return result;
}

 

이 예제는 params를 통해 가변적으로 매개변수를 받을 수 있는 방법을 보여주고 있습니다. 방식은 일반적인 배열과 비슷하게 처리하는 것인데 차이점이라면 메서드를 호출하는 쪽에서 배열전달을 위한 별도의 작업을 해줄 필요가 없고 보통 메서드를 호출하는 방식을 그대로 사용할 수 있다는 것입니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] 인증및 접근제어와 로그인  (0) 2019.04.11
[C#] yield  (0) 2019.04.02
[C#] params  (0) 2019.03.19
[C#] HttpWebRequest / HttpWebResponse / WebClient  (0) 2019.03.12
[C#] 시프트(Shift) 연산자  (0) 2019.03.05
[C#] 예외처리(try ~ catch)  (0) 2019.02.19
0 0
Programming/.NET

System.Net.HttpWebRequest 는 HTTP 통신을 위한 요청을 자동으로 만들어 주며 System.Net.HttpWebResponse는 그에 대한 응답을 해석해주는 클래스입니다.

 

HttpWebRequest hwreq = (HttpWebRequest)WebRequest.Create("http://www.naver.com");
HttpWebResponse hwres = (HttpWebResponse)hwreq.GetResponse();

StreamReader sr = new StreamReader(hwres.GetResponseStream());
File.WriteAllText("default.htm", sr.ReadToEnd());
sr.Dispose();

Console.WriteLine("다 됐음");

 

우선 HttpWebRequest로 특성 URL에 대한 요청을 만들어 GetResponse 메서드로 응답을 받습니다. 이때 응답을 HttpWebResponse형식으로 받아 스트림으로 처리하면 응답내용을 확인할 수 있습니다.

 

WebClient는 쉽게 HttpWebRequest 와 HttpWebResponse를 좀더 추상화한 것으로 보면 됩니다. 너무 간단해서 설명조차 필요없을듯 합니다.

 

WebClient wc = new WebClient();
File.WriteAllText("default.htm", wc.DownloadString(http://www.naver.com/));

 

DownloadString 메서드는 요청에 대해 응답해오는 데이터를 문자열로 받아오도록 합니다. WebClient에는 이외에도 HTTP관련 다양한 메소드를 제공하고 있습니다.

'Programming > .NET' 카테고리의 다른 글

[C#] yield  (0) 2019.04.02
[C#] params  (0) 2019.03.19
[C#] HttpWebRequest / HttpWebResponse / WebClient  (0) 2019.03.12
[C#] 시프트(Shift) 연산자  (0) 2019.03.05
[C#] 예외처리(try ~ catch)  (0) 2019.02.19
[C#] ? / Nullable  (0) 2019.02.12
0 0
Programming/.NET

비트 단위의 데이터연산시 사용합니다. 예를 들어 정수 10은 비트값으로 아래와 같습니다.

 

00000000 00001010

 

참고로 32나 64비트에 따라 자리수만큼 표시되어야 하지만 간소화를 위해 16비트로 표시하였습니다.

 

시프트연산자는 이 비트를 오른쪽으로 혹은 왼쪽으로 0을 채워 밀어주는 역활을 수행 합니다.

 

int i = 10;

int leftShift = i << 3;
int rightShift = i >> 3;

Console.WriteLine("Result : {0} | {1}", leftShift, rightShift);

 

<< 표시는 왼쪽 시프트연산자이며 >> 표시는 오른쪽 시프트연산자입니다. 이 연산자에 따라 10 (1010)을 왼쪽으로 3개의 비트를 밀면

 

00000000 01010000

 

이 되고 이 비트를 10진수 정수로 변환하면 80이 됩니다. 반면 오른쪽으로 3개비트를 밀게되면

 

00000000 00000001

 

이 되어 결과는 1이 됩니다.

 

이 연산방식은 왼쪽시프트는 1비트씩 움직일때 마다 2를 곱한것과 같고 오른쪽 시프트는 2로 나눈것과 같은 값이 됩니다.

'Programming > .NET' 카테고리의 다른 글

[C#] params  (0) 2019.03.19
[C#] HttpWebRequest / HttpWebResponse / WebClient  (0) 2019.03.12
[C#] 시프트(Shift) 연산자  (0) 2019.03.05
[C#] 예외처리(try ~ catch)  (0) 2019.02.19
[C#] ? / Nullable  (0) 2019.02.12
[C#] partial  (0) 2019.02.07
0 0
1
블로그 이미지

클리엘