2014-10-15 2 views
3

처음에는 세 개의 테이블이 있으며 모두 기본 키와 다른 데이터가 있습니다. 이 테이블은 7 천만 개의 행이있는 조인 테이블에 조인됩니다. Table_1, Table_2, Table_3.테이블 인덱스 성능 향상 관련 문제

Table_3_Id, Table_1_Id, Table_2_Id (이 순서대로)에이 조인 테이블에 기본 키가 있습니다. 또한 채우기 색인이 Table_1_Id, Table_2_Id, Table_3_Id (순서대로) 이상인 클러스터되지 않은 색인이 있습니다.

데이터는 Table_1_Id (이 ID 중 ~ 100 개가 사전 설정되어 있음) 및 (조인을 통해) Table_3의 속성을 사용합니다 (따라서 Table_3_Id를 사용합니다). 그런 다음 Table_1_Id 및 Table_2_Id 값이 반환됩니다. 이 모든 작업은 Entity Framework에서 하나의 쿼리로 수행됩니다.

var items = dataContext.TablesJoin.AsNoTracking() 
      .Join(dataContext.Table_3.AsNoTracking(), x => x.Table_3_Id, x => x.Id, (combi, scan) => new { combi, scan }) 
      .Where(x => possibleIds.Contains(x.combi.Table_1_Id) && otherIds.Contains(x.scan.Other_Id)) 
      .Select(x => new { FirstId = x.combi.Table_1_Id, SecondId = x.combi.DeviceInformationDevices_Id }) 
       ToList(); 

이 구성은 SQL Server Express가 실행되고 있기 때문에, 내가 어떤 공간 문제 (10기가바이트가 최대입니다) 실행 해요 :

은 쿼리입니다. 데이터는 약 2GB이지만 기본 키와 색인은 총 5GB입니다. 데이터베이스에 더 많은 데이터가 있기 때문에 성능을 유지하면서 인덱스 크기를 줄이는 데 관심이 있습니다.

모든 것을 살펴본 후에, 정확히 무엇이 사용되는지에 대한 우려가있었습니다. 조인 때문에 클러스터되지 않은 인덱스에 Table_3_Id를 포함시키는 것이 얼마나 유용한 지 분명하지 않습니다. 색인에서이 열을 제거하면 약 1GB의 공간이 절약됩니다.

처음에는이 테이블을 안전한 공간에 클러스터 된 인덱스로 사용했지만 테이블에 많은 삽입 (1000/시간)이 있었기 때문에 모든 디스크 액세스로 인해 테이블이 끊임없이 스왑되므로 데이터 10GB. 이 문제를 해결하기 위해 채우기 비율을 낮추면 (70처럼) 도움이 될까요? 물론, 더 많은 낭비 된 공간을 의미 할 수도 있지만, 이것이 인덱스에 많은 도움을 줄 수 있다면 가치가있을 것입니다.

이 표는 많이 사용되며 성능을 위해 색인이 필요합니다. 인덱스없이 실행하면 몇 분 정도의 시간이 소요되는 반면 인덱스는 2 초 이내에 완료됩니다.

실행 계획 XML : http://pastebin.com/raw.php?i=tfUxgYrK

+1

이 쿼리를 최적화하는 데 관심이 있습니까? 실행중인 DML에 대해 자세히 알려주십시오. 보유하고있는 현재 최상의 설정의 XML 실제 실행 계획을 업로드하십시오. – usr

+0

왜 여러 데이터베이스에서 이것을 분리하여 10 기가 바이트 제한에서 벗어나지 않습니까? 트리거는 참조 무결성을 처리 할 수 ​​있습니다. 또는 더 나은 데이터베이스를 얻으십시오. 웹 에디션은 비용이 많이 들지 않으며 익스프레스 에디션으로 계속해서 한계에 부딪치게됩니다. – TomTom

+0

나눌 수 있지만이 테이블은 이미 10GB 한도 (7GB)의 대부분을 차지하고 있기 때문에 이것은 단지 몇 개월의 지연이며 실제로 도움이되지 않습니다. 데이터를 여러 데이터베이스로 나눌 수 있지만 모든 것이 지나치게 복잡해질 수 있습니다. 나는 웹 에디션을 구입할 수 있다고 생각하지 않는다. 판매용으로는 어디에도 보지 못했다. 실행 계획을 얻을 수 있는지 보겠습니다. 필자는이 쿼리를 충분히 최적화하지는 않았지만이 테이블의 크기를 줄이는 데 그쳤습니다. 인덱스는 2GB의 데이터를 5GB로 차지합니다. –

답변

1

당신은 고유성에 대한 기본 키가 필요하지 않습니다. NCI는 이미 그 고유성을 제공합니다. 이러한 인덱스 중 하나를 제거 할 수 있습니다. 그러면 공간이 절약됩니다.

다른 인덱스가 클러스터링하여 사용하는 공간을 절약 할 수 있습니다. 외관상으로는 무작위로 위치한 삽입물로 인해 성능 문제가 있음을 알 수 있습니다. 이것은 그럴듯합니다. 삽입이 한 곳 또는 몇 곳에서만 일어나도록 색인의 열 순서를 변경하십시오. 이렇게하면 영향을받는 모든 페이지가 캐싱되는 경향이 있습니다. DML에 필요한 작업 세트는 낮습니다.

DML perf 문제는 아마도 페이지 분할로 인한 것이 아닙니다. 이로 인해 주로 CPU로드 및 조각화가 발생합니다. perf 문제는 디스크에서 임의 페이지를 읽어야하기 때문에 발생했을 수 있습니다.

시간당 1000 개의 삽입물이 많지 않습니다. 작고 완전히 캐싱 된 델타 테이블에 쓰기를 축적하는 것을 고려하십시오. 백그라운드 프로세스에서 행을 주 테이블로 이동하십시오. 그렇게하면 DML 대기 시간이 중요한 경로를 벗어납니다. 선택 사항은 staleness를 허용해야하거나 UNION ALL 델타 테이블을 허용해야합니다.

+0

NCI에는 현재 유일성 제약 조건이 없습니다. 이는 PK 공간을 절약하는 좋은 아이디어 인 것 같습니다. 순서와 관련해서는별로 중요하지 않습니까? 새 항목을 추가하는 사용자 당, Table_3_Id에 대해 비슷한 100 개의 값, Table_2_Id에 대해 50 개의 유사한 값 및 Table_2_Id에 대해 100 개의 고유 한 값. Table_3_Id에는 700000 개의 다른 값이 있고 Table_2_Id에는 500000 개의 값이 있으며 Table_1_Id에는 500000 개의 값이 있습니다. 채우기 요소가 여기에서 도움이 될까요? 성능 문제는 삽입 (매우 높은 CPU 및 디스크 사용이 sqlservr.exe에 대해 나타남)과 함께 잘 수행되었습니다. 나는 당시 필 팩터가 95였다. –

+0

채우기 비율은 페이지 분할에 도움이되지만 시간당 1000 개의 행이 어떤 방식 으로든 페이지 분할로 인해 높은 CPU를 유발할 수는 없습니다. 다른 뭔가가 있어야합니다. DML 실행 계획을 게시하고 싶다면 삽입하는 열의 대부분이 ID 나 타임 스탬프와 같이 순차적으로 삽입됩니까? 이 열은 작은 작업 집합에 작업을 집중시키는 데 유용한 주요 색인 열입니다. 그것은 선택을위한 색인을 사용하여 그러나 끊을지도 모르다. – usr

+0

실행 계획이 시작 지점에 있습니다 (http://pastebin.com/raw.php?i=tfUxgYrK). Table_3_Id는 어느 정도의 순서 (100 배의 1 배, 100 배의 2 배, 100 배의 3 배 등)를 가지는 유일한 열입니다. 인서트는 나중에 한 달에 한 번 같은 값으로 발생하지만 한 번에 몇 개만 (5-6) 발생합니다. –