2014-01-17 3 views
2

특정 반경 (마일) 이내의 항목 목록을 검색하려고 할 때 가장 빠른 검색을 위해 데이터베이스와 mvc 응용 프로그램을 구성하는 가장 좋은 방법은 무엇입니까? 또한 우편 번호에 따라 다릅니다. 나는 그것이 나의 현재의 설정에 변화를 포함한다고해도 제안에 개방적이다. 나는 현재 우편 번호 및 위도/경도를 포함하는 .txt 파일을 사용하고거리 조회를위한 데이터베이스와 프로그램을 구성하는 가장 좋은 방법

Simple Schema

는 거리를 계산하는 좌표. Haversine Formula을 사용하면 좌표를 사용하여 두 점 사이의 거리를 계산할 수 있습니다.

내 인덱스 컨트롤러에서 내 데이터를 페이징하기 위해 PagedList 1.17.0.0을 사용하고 있습니다. 내가 직면 한 주된 문제는 EF와 관련이 있습니다. 50 마일 거리 내에서 항목을 선택할 때 SQL 문이 너무 중첩되어 EF에서 오류가 발생합니다. 제어기

public ActionResult Index(string sortOrder, string Categories, string Manufacturers, int? page, bool clearFilters = false 
     ,string DistanceLimit = "", int Vehicle = 0) 

파라미터 섹션에서 각 스트링

전류는 EF를 사용하기위한 가능한 필터이다. 이후 EF를 object.Where(P => P.Distance <= 50)

으로 지정하지 못합니다. 문자열 작성기를 사용하여 원시 쿼리를 생성합니다. 내 ZipCode 클래스는 반경 50 마일 이내의 모든 zip을 검색 한 다음 각 zip 코드를 where 절의 매개 변수로 사용하여 간단한 선택을 구성합니다. 여기서 where 절이 너무 많아서 문제가 발생합니다. 25 마일 반경은 괜찮지 만 50은 아닙니다.

위의 기능이 작동하면 해당 거리 내의 항목의 기본 키를 가져옵니다. 그때 Item.Include(P => P.Manufacturer).Include(P => P.Category).Include(3 other tables)

그때 내 IQueryableToList() 전화 및 PK와 내 이전 목록 내에 있지 않은 모든 Item의 제거를 선택 EF 있습니다.

마지막으로 ToPagedList()으로 전화하여 viewmodel 내에서 내보기로 되돌립니다.

여기서 알 수 있듯이 많은 부분이 있습니다.

하나의 경우 : 반경 25 마일을 초과하여 작동하지 않습니다.

: 지나치게 복잡하고 Rube Goldberg 시스템처럼 느껴집니다.

:이 모든 개별 쿼리 실행은 검색 결과 속도에 중요한 영향을줍니다.

이전에 말했듯이 비슷한 기능을 가진 시스템을 만든 사람이라면 누구에게나 제안을 할 수 있습니다. 필자는 지형 공간 데이터를 다뤄 본 적이 없으며 최근에 SQL Server의 지리 유형을 알고 있습니다. 그러나, 나의 이해에서, 나는 어느 항목이 근처에 있는지 알아 내기 위해 모든 위도/경도 기록에 StDistance를 호출해야 할 것 같다. 말할 필요도없이 내 .txt 파일을 dB로 이동해야합니다.

+1

SQL에 대한 테이블 반환 매개 변수를 확인하십시오. http://stackoverflow.com/questions/5595353/how-to-pass-table-value-parameters-to-stored-procedure-from-net-code where 절을 추가하는 대신 우편 번호 테이블에 간단히 가입 할 수 있습니다. –

+0

얼마나 자주 항목 테이블이 변경됩니까? 그것은 꽤 정적입니까? 얼마나 많은 행이 있습니까? –

+0

@simonatrcl 항목의 테이블이 많이 변경됩니다. 기본적으로 판매용 카탈로그입니다. 내가 나중에 게시 할 테이블 값 매개 변수를 사용하여 솔루션을 알아 냈습니다. – Adrian

답변

1

반지름을 기준으로 항목을 검색 할 때 회사에서 동일한 문제를 처리해야했습니다. 우리가 필요로하는 각 항목에 대해 Lat, Long 데이터베이스에 이미 저장 한 데이터의 유일한 차이점입니다. 경우에 따라 서버가 반환되는 동안 추가 작업을 제거하기 위해 GeographyPoint 데이터 형식을 사용하기 시작했습니다. 일부 도구는 Geography 데이터 형식을 만들 수 없어 사용이 제한됩니다.

이 예제는이 작업을 수행하는 데 사용하는 저장 프로 시저의 예제입니다. 의견을보세요.

CREATE PROCEDURE [dbo].GetItems_ByRadius 
(
@pLat DECIMAL(20, 13)  --= 35.151 
,@pLon DECIMAL(20, 13)  --= -86.59 
,@pRadius DECIMAL(7, 2)  --= 2 
) 
AS 
BEGIN 
    SET NOCOUNT ON; 
    /*Declare Local Variables to avoid parameter sniffing*/ 
    DECLARE @Lat VARCHAR(20) = @pLat 
     ,@Lon VARCHAR(20) = @pLon 
     ,@Radius DECIMAL(7, 2) = @pRadius 
     ,@Earth_Radius INT = 6371000 

    /*Declare additional variables that are needed for calculations*/ 
    DECLARE @Distance DECIMAL(10, 2) = @Radius * 1609.344 
     ,@Point_geo GEOGRAPHY 
     ,@Min_Lat DECIMAL(20, 13) 
     ,@Max_Lat DECIMAL(20, 13) 
     ,@Min_Long DECIMAL(20, 13) 
     ,@Max_Long DECIMAL(20, 13) 

    /*Convert original Lat Long parameters to GeographyPoint this will be used to check radius distance*/ 
    SET @Point_geo = GEOGRAPHY::STGeomFromText('POINT(' + @Lon + ' ' + @Lat + ')', 4326) 

    /*Build Bounding Box*/   
    SET @Min_Lat = @Lat - DEGREES(@distance/@Earth_Radius) 
    SET @Max_Lat = @Lat + DEGREES(@distance/@Earth_Radius)  
    SET @Min_Long = @Lon - DEGREES(@distance/@Earth_Radius/COS(RADIANS(@Lat))) 
    SET @Max_Long = @Lon + DEGREES(@distance/@Earth_Radius/COS(RADIANS(@Lat))); 

    WITH MyBoxResults 
       AS (SELECT * 
         ,GEOGRAPHY::STPointFromText('POINT(' + CAST(Geog_Long AS VARCHAR(20)) + ' ' 
                + CAST(Geog_Lat AS VARCHAR(20)) + ')', 4326) AS GeogLocation 
        FROM MyTable 
        WHERE (Geog_Lat BETWEEN @Min_Lat AND @Max_Lat) 
         AND (Geog_Long BETWEEN @Min_Long AND @Max_Long)) \ 
/*Using Long and Lat decimal columns we get results that are within the box that surrounds radius*/ 
     SELECT * 
      FROM MyBoxResults 
      WHERE @Point_geo.STDistance(GeogLocation) <= @Distance; 
/*This further limits results to only the radius instead of original box.*/ 

END 

절차 내에서 우리는 성능을 향상시키는 몇 가지 방법을 만들었습니다.
- 위도 및 긴 컬럼에 인덱스를 빠르게 수행 할 수있는 경계 상자에 결과를 제한하는 데 사용 CTE - 지역 변수의 사용이 Read here more about it
를 스니핑 매개 변수를 방지 할 수 있습니다. - Geography functions 및 perticular를 사용하는 경우에만 STDistance. 해당 함수가 제한된 결과 대신 전체 데이터 집합에 사용되는 경우 프로 시저가 반환하는 데 훨씬 오래 걸립니다.

절차에 대해 궁금한 점이 있으면 알려주십시오.

관련 문제