2010-08-10 5 views
5

순차적 GUID가 일반 GUID보다 어떻게 더 잘 수행되는지 이해하려고합니다.순차적 GUID 및 단편화

정규 GUID를 사용하면 인덱스가 GUID의 마지막 바이트를 사용하여 정렬 할 수 있습니까? 랜덤이기 때문에 종종 새로운 데이터를 삽입하기 위해 데이터를 다른 페이지로 이동시킬 것이므로 조각화와 페이지 분할이 많이 발생합니까?

순차적 인 가이드 순차적 인 페이지 분할 및 조각화가 덜 발생합니다.

내 이해가 정확합니까?

피사체에 더 많은 빛을 비출 수있는 사람은 대단히 감사하겠습니다.

감사합니다

편집 : GUID = NEWSEQUENTIALID()

연속,

정기 GUID = NEWID() 나는이 주제에 대한 킴벌리 L. 트립의 지혜로 연기

+0

"순차적 guid", 특히 "일반 guid"의 의미를 정의 할 수 있습니다. –

+2

@ 그렉 : 나는 그가 "순차적 GUID"를 NEWSEQUENTIALID()가 생성 한 것과 "일반 GUID"를 NEWID()가 생성했다는 것을 믿는다. –

답변

8

당신은 꽤 많이 귀하의 질문에 모든 것을 말했다했습니다.

순차 GUID/기본 키를 사용하면 새 행이 테이블 끝 부분에 함께 추가되므로 SQL Server에서 쉽게 사용할 수 있습니다. 비교할 때 임의 기본 키는 새로운 레코드가 테이블의 어느 위치 에나 삽입 될 수 있음을 의미합니다. 캐시에있는 테이블의 마지막 페이지가있을 가능성이 있습니다 (모든 읽기가 진행되는 경우). 캐시에있는 테이블 중간의 무작위 페이지가 상당히 낮아 추가 IO가 필요합니다.

테이블의 가운데에 행을 삽입 할 때 여분의 행을 삽입 할 충분한 공간이 없을 가능성이 있습니다. 이 경우 SQL Server는 레코드 공간을 확보하기 위해 추가로 값 비싼 IO 작업을 수행해야합니다.이를 피할 수있는 유일한 방법은 여분의 레코드를 삽입 할 수 있도록 데이터 사이에 간격을 두는 것입니다 (채우기 비율). 데이터가 더 많은 페이지에 분산되어 전체 테이블에 액세스 할 때 더 많은 IO가 필요하기 때문에 성능 문제가 발생합니다.

+0

Thank you! 나는 그걸 정확하게 이해했는지 확인하고 싶었습니다. – pdiddy

2

:

그러나 순차적이지 않은 GUID - 은 h 그것의 클라이언트에서 생성 값으로 (.NET을 사용) 을 OR (SQL Server의)가 NEWID() 함수 에 의해 생성 된 끔찍하게 나쁜 선택이 될 수 있습니다 - 주로 때문에이 기본 테이블에 작성하는 분열의 크기가 이기도합니다. 불필요하게 넓습니다 (int 기반의 ID 인 보다 4 배 더 넓어서 20 억 (실제로는 40 억)의 고유 한 행을 제공 할 수 있습니다. 그리고 만약 당신이 20 억 이상 필요하다면 은 항상 bigint (8 바이트의 int)와 함께 갈 수 있고 263-1 개의 행을 얻을 수 있습니다.

더 읽기 : http://www.sqlskills.com/BLOGS/KIMBERLY/post/GUIDs-as-PRIMARY-KEYs-andor-the-clustering-key.aspx#ixzz0wDK6cece

+0

Sequential Guid를 사용하면 순차적이므로 기술적으로 모든 새로운 인덱스 페이지는 이론 순차적 일 것이다. 따라서 성능을 향상시킵니다. 나는 그것을 올바르게 이해하고 있는가? 정기적 인 GUID를 위해 그것은 무작위 적이기 때문에 레코드가 모든 곳에서있을 것입니다. 따라서 범위가있는 정규 select 문을 수행하는 것이 느려질 수 있습니다? – pdiddy

+0

@pdiddy - "임의"GUID가 순차적이지 않기 때문에 왜 그 범위를 선택하겠습니까? – JNK

+2

당신은 순차 대 무작위 성격에 대해 정확하지만, 진짜 고통은 SELECT가 아니라 INSERT에 있습니다. –

0

전체 그림을 시각화하려면 util named ostress을 사용할 수 있습니다. 예.PK로 정상 GUID, 순차적 GUID 또 다른 하나 :

ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTable VALUES (NEWID()); SELECT count(*) AS Cnt FROM dbo.YourTable; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTable';" -oE:\incoming\TMP\ -n1 -r10000 

ostress -Slocalhost -E -dYourDB -Q"INSERT INTO dbo.YourTableSeq DEFAULT VALUES; SELECT count(*) AS Cnt FROM dbo.YourTableSeq; SELECT AVG_FRAGMENTATION_IN_PERCENT AS AvgPageFragmentation, PAGE_COUNT AS PageCounts FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, N'LIMITED') DPS INNER JOIN sysindexes SI ON DPS.OBJECT_ID = SI.ID AND DPS.INDEX_ID = SI.INDID WHERE SI.NAME = 'PK_YourTableSeq';" -oE:\incoming\TMP\ -n1 -r10000 
: 당신은 인덱스 조각화에 대한 통계의 선택과 삽입의 numbero을 실행 util을 주어진와 그런

-- normal one 
CREATE TABLE dbo.YourTable(
    [id] [uniqueidentifier] NOT NULL, 
    CONSTRAINT [PK_YourTable] PRIMARY KEY NONCLUSTERED (id) 
); 
-- sequential one 
CREATE TABLE dbo.YourTableSeq(
    [id] [uniqueidentifier] NOT NULL CONSTRAINT [df_yourtable_id] DEFAULT (newsequentialid()), 
    CONSTRAINT [PK_YourTableSeq] PRIMARY KEY NONCLUSTERED (id) 
); 

두 개의 테이블을 만들 수 있습니다

파일 E : \ incoming \ TMP \ query.out에서 통계를 찾을 수 있습니다. 내 결과는 다음과 같습니다 삽입 작업이 새 페이지 할당 희소 리드로

"Normal" GUID: 
Records AvgPageFragmentation  PageCounts   
---------------------------------------------- 
1000  87.5      8      
2000  93.75     16     
3000  96.15384615384616  26     
4000  96.875     32     
5000  96.969696969696969  33     
10000  98.571428571428584  70     


Sequential GUID: 
Records AvgPageFragmentation  PageCounts   
---------------------------------------------- 
1000  83.333333333333343  6      
2000  63.636363636363633  11     
3000  41.17647058823529  17     
4000  31.818181818181817  22     
5000  25.0      28     
10000  12.727272727272727  55  

순차적으로 GUID가 삽입되는 생성과 당신이 볼 수 있듯이, 인덱스가 훨씬 덜 조각입니다.