2010-03-16 3 views
0

나는 이전의 question에서 SQL에 대한 좋은 답에 영감을 받았습니다. 이 SQL은 Interbase 2009를 사용하는 DB에서 실행됩니다. 크기는 약 21GB입니다.Interbase로 SQL 최적화

SELECT DistanceAsMeters, AddrDistance.Bold_Id, AddrDistance.Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity 
FROM AddrDistance 
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id 
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id 
Where DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0 
     and not AddrDistance.bold_id in (select bold_id from DistanceQueryTask) 
Order By Created Desc 

은 AddrDistance와 840,000 행 190000 주소와 행과 DistanceQueryTask 4 있습니다.

질문은 더 빠를 수 있습니까? 같은 쿼리가 여러 번 실행됩니다. select bold_id from DistanceQueryTask.

Statement: SELECT DistanceAsMeters, AddrDistance.Bold_Id, AddrDistance.Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity 
FROM AddrDistance 
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id 
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id 
Where DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0 
     and not AddrDistance.bold_id in (select bold_id from DistanceQueryTask) 
Order By Created Desc 

PLAN (DISTANCEQUERYTASK INDEX (RDB$PRIMARY218)) 
PLAN SORT (JOIN (JOIN (ADDRDISTANCE NATURAL,ADDRESSFROM INDEX (RDB$PRIMARY234)),ADDRESSTO INDEX (RDB$PRIMARY234))) 

그리고 네, DistanceQueryTask는 의미 행의 경우 낮은 숫자를 가지고 : 나는, 그냥 일반 SQL : 여기

EDIT1

현재 실행 계획입니다 저장 프로 시저에 관심이 아니에요합니다 데이터베이스에.

+0

쿼리 실행 계획을 확인 했습니까? (IBX 구성 요소, IBExpert 및 IBConsole을 사용하여 수행 할 수 있습니다)? 인덱스 대신 자연 조인이 있는지를 보여줍니다. – mjn

+0

DistanceQueryTask에는 항상 적은 수의 레코드가 포함됩니까? – skamradt

답변

2

왼쪽 결합 및 하위 쿼리를 사용하면 쿼리 속도가 느려집니다.

당신은 올바른 인덱스 약간의 개선을 얻을 수 있습니다 (Bold_id에 DistanceMeters는 PseudoDistanceAsCostKm은) 이상의 인덱스는 데이터베이스

+1

이러한 필드를 인덱싱 할 때 가장 큰 개선점이 있습니다. 감사합니다. –

2

내가 bold_id 당신의 열쇠 가정, 따라서 제대로 인덱스의 크기를 증가 기억 해요.
그런 다음 subselect와 not ... in을 조인으로 바꾸면 옵티 마이저에 도움이 될 수 있습니다.

SELECT DistanceAsMeters, Bold_Id, Created, AddressFrom.CityName_CO as FromCity, AddressTo.CityName_CO as ToCity 
FROM AddrDistance 
LEFT JOIN Address AddressFrom ON AddrDistance.FromAddress = AddressFrom.Bold_Id 
LEFT JOIN Address AddressTo ON AddrDistance.ToAddress = AddressTo.Bold_Id 
LEFT JOIN DistanceQueryTask ON AddrDistance.bold_id = DistanceQueryTask.bold_id 
Where DistanceAsMeters = 0 and PseudoDistanceAsCostKm = 0 
    and DistanceQueryTask.bold_id is null 
Order By Created Desc 
+0

이 쿼리는 0 행을 제공합니다. 이는 행을 식별하는 데 사용되는 키이므로 거리 확인 쿼리가 null이 아니기 때문일 수 있습니다. 그 외에 AddrDistance와 DistanceQueryTask의 bold_id는 결코 같을 수 없다. –

+0

@Roland : 'right_table.Key is null'과 결합 된 왼쪽 조인은 오른쪽 테이블 (where 절없이 right_table 열이 null 인 테이블)에 일치하지 않는 왼쪽 테이블의 레코드 만 제공합니다. –

2

이 부분에 대한 인덱스를 작성 : 그것은 않기 때문에 (DistanceAsMeters = 0 및 PseudoDistanceAsCostKm = 0) 그것을 위해 (나쁜) 테이블 스캔 : ADDRDISTANCE 자연

그리고 노력이 (가) 대신 조인을 사용하는 프랑소와 (Francois)가 말한 바와 같이 subselect.

2

다니엘과 앙드레가 색인을 제안함에 따라 많은 도움이됩니다.
인덱스의 첫 번째 두 부분이 일정하기 때문에이 인덱스 (DistanceMeters, PseudoDistanceAsCostKm, Bold_id)를 제안한 다음 읽을 필요가있는 인덱스의 작은 부분입니다.

FromAddress 및/또는 ToAddress가있는 경우 LEFT JOIN을 INNER JOIN으로 변경할 수 있습니다 (쿼리 최적화 프로그램에서 일부 가정을 할 수 있음).