필터링 된 검색을 구현하는 가장 좋은 방법


17

필터링 된 검색 양식을 구현할 때 귀하의 의견을 묻고 싶습니다. 다음과 같은 경우를 상상해 봅시다.

  • 1 열이 많은 큰 테이블
  • 이 SQL Server를 말하는 것이 중요 할 수 있습니다

이 표의 데이터를 검색하기위한 양식을 구현해야하며이 양식에는이 검색을 계산할 수있는 몇 개의 확인란이 있습니다.

이제 내 질문은 다음 중 검색을 구현하는 가장 좋은 방법은 무엇입니까?

  1. 내부에 쿼리를 사용하여 저장 프로 시저를 만듭니다. 이 저장 프로시 저는 응용 프로그램에서 매개 변수를 제공하는지 확인하고 매개 변수가 제공되지 않은 경우 쿼리에 와일드 카드를 넣습니다.

  2. 응용 프로그램에서 제공 한 내용에 따라 작성된 동적 조회를 작성하십시오.

SQL Server가 저장 프로 시저를 만들 때 성능을 최적화하기 위해 실행 계획을 작성한다는 것을 알고 있기 때문에이를 묻습니다. 그러나 저장 프로 시저 내부에 동적 쿼리를 작성하면 실행 계획으로 얻은 최적화를 희생합니까?

귀하의 의견에 가장 적합한 방법을 알려주십시오.


당신은 아래에서 당신이 역동적 인 해결책을 찾고 있다고 말합니다. 멋지다. 가능한 필터를 열거하고 인덱스를 지원하는 인덱스가 있는지 확인하십시오. 쿼리가 일관되게 구축되는 한 효율적이어야합니다.
Matthew Flynn

답변:


10

/programming/11329823/add-where-clauses-to-sql-dynamically-programmatically 비슷한 질문에 대한 답변을 볼 수 있습니다

우리는 많은 선택적 매개 변수를 취하고 다음과 같이 필터를 구현하는 SPROC를 발견했습니다.

CREATE PROC MyProc (@optionalParam1 NVARCHAR(50)=NULL, @optionalParam2 INT=NULL)
AS 
...
SELECT field1, field2, ... FROM [Table]
WHERE 
  (@optionalParam1 IS NULL OR MyColumn1 = @optionalParam1)
  AND (@optionalParam2 IS NULL OR MyColumn2 = @optionalParam2)

는 실행 된 첫 번째 실행 계획을 캐시 @optionalParam1 = 'Hello World', @optionalParam2 = NULL하지만 (예 :) 다른 선택적 매개 변수 세트 (예 :)를 전달하면 비참하게 수행됩니다 @optionalParam1 = NULL, @optionalParam2 = 42. (그리고 분명히 우리는 캐시 된 계획의 성능을 원합니다. WITH RECOMPILE)

여기서 선택적 매개 변수 외에 매우 선택적이고 적절하게 인덱싱 된 쿼리에 하나 이상의 MANDATORY 필터가있는 경우 위의 PROC가 제대로 수행됩니다.

그러나 모든 필터가 선택 사항 인 경우 매개 변수가있는 동적 SQL은 실제로 성능이 더 우수하다는 것입니다 (선택적 매개 변수의 각 순열에 대해 N! 다른 정적 PROCS를 쓰지 않는 한).

아래의 동적 SQL은 쿼리 매개 변수의 각 순열에 대해 다른 계획을 만들고 캐시하지만 적어도 각 계획은 특정 쿼리에 대해 '맞춤화'됩니다 (PROC인지 Adhoc SQL인지는 중요하지 않음). 매개 변수가있는 쿼리 인 경우 캐시됩니다)

따라서 내 선호도가 :

DECLARE @SQL NVARCHAR(MAX)        

-- Mandatory / Static part of the Query here
SET @SQL = N'SELECT * FROM [table] WHERE 1 = 1'

IF @OptionalParam1 IS NOT NULL        
    BEGIN        
        SET @SQL = @SQL + N' AND MyColumn1 = @optionalParam1'    
    END        

IF @OptionalParam2 IS NOT NULL        
    BEGIN        
        SET @SQL = @SQL + N' AND MyColumn2 = @optionalParam2'    
    END        

EXEC sp_executesql @SQL,        
    N'@optionalParam1 NVARCHAR(50), 
      @optionalParam2 INT'
    ,@optionalParam1 = @optionalParam1
    ,@optionalParam2 = @optionalParam2

sp_executesql에 중복 매개 변수를 전달해도 상관 없습니다. 무시됩니다. Linq2SQL 및 EF와 같은 ORM은 비슷한 방식으로 매개 변수화 된 동적 SQL을 사용한다는 점에 주목할 가치가 있습니다.


1
네, 그렇게 생각했습니다. 이것이 제가 선택한 옵션입니다. 그냥 좋은지 확인하고 싶었습니다. 답변 주셔서 감사합니다.
j0N45

"매개 변수없이 SQL 문을 실행하면 SQL Server는 해당 문을 내부적으로 매개 변수화하여 기존 실행 계획과 일치시킬 가능성을 높입니다.이 프로세스를 단순 매개 변수화라고합니다." 기본적으로 프로그램은 "where filenumber ="+ filename과 같은 것을 사용할 수 있습니다. 물론, 그것은 벌레의 깡통을
열지

5

구현하기 쉽다고 생각하는 것부터 시작하십시오 (옵션 2). 그런 다음 실제 데이터의 성능을 측정 하십시오. 필요할 때만 최적화를 시작하십시오.

그런데 검색 필터가 얼마나 복잡한 지에 따라 동적 SQL이 없으면 작업을 쉽게 해결할 수 없습니다. 따라서 저장 프로 시저를 사용하더라도 이미 예상 한 것처럼 성능이 향상되지는 않습니다. 반면에 도움이된다면 SQL에 추가 할 수 있는 몇 가지 유형의 힌트가 있습니다 ( http://www.simple-talk.com/sql/performance/controlling-execution-plans-with-hints/ 참조 ) SQL 서버가 실행 계획을 최적화하는 데 도움이되는 동적 쿼리 또는 동적 쿼리


글쎄, 나는 이미 옵션 2를 구현했으며 이것이 와일드 카드가 성능을 크게 저하시키기 때문에 가장 좋은 방법이라고 생각하지만 유지 관리를 희생하고 있습니다. 코드의 복잡성이 증가하기 때문입니다. 나는 누군가가 이런 종류의 상황에 더 나은 옵션을 알고 있는지 알고 싶었습니다.
j0N45

나는 당신에게 투표권을 줄 것이지만, 죄송합니다.
j0N45
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.