준비된 SQL 배치를 실행하는 것과 별도로 SQL 배치를 준비하는 것은 효과적으로 **실행 계획이 캐시되는 방식을 감안할 때 SQL Server에는 쓸모가 없습니다. 준비 단계 (파싱, 매개 변수 바인딩 및 컴파일)를 분리하고 실행하는 것은 캐싱이없는 경우에만 의미가 있습니다. 기존 계획을 재사용하여 구문 분석 및 컴파일에 소요되는 시간을 절약하는 것이 목적이며, 이는 내부 계획 캐시의 기능입니다. 그러나 모든 RDBMS가 이러한 수준의 캐싱을 수행하는 것은 아니며 (이러한 기능의 존재로 인해) 계획을 "캐싱"하도록 요청하고 캐시 ID를 저장 한 다음 재사용하는 것은 클라이언트 코드에 달려 있습니다. 그것. 이는 불필요한 클라이언트 코드 (및 프로그래머가 기억하고 올바르게 기억해야 함)에 대한 추가 부담입니다. 실제로 IDbCommand.Prepare () 메서드에 대한 MSDN 페이지는 다음 과 같습니다.
서버는 필요에 따라 재사용 계획을 자동으로 캐시합니다. 따라서 클라이언트 애플리케이션에서이 메소드를 직접 호출 할 필요가 없습니다.
SqlCommand.Prepare ()를 호출하는 내 테스트 쇼 (질문에 표시된 것과 일치) 가 "준비"전용 작업을 수행 하지 않는 경우 SQL 을 준비 하고 실행하는 sp_prepexec 를 호출합니다. ; 그것은 호출하지 않습니다 sp_prepare 구문 분석하고 컴파일 만 (및 매개 변수 값, 그들의 이름과 데이터 유형에 고려하지 않습니다). 따라서 즉시 실행을 수행하기 때문에 호출의 "사전 컴파일"이점이 없습니다 (목표는 실행을 지연시키는 것으로 가정). 그러나 이라고 전화하더라도 호출의 흥미로운 잠재적 이점이SqlCommand.Prepare
SqlCommand.Prepare()
sp_prepexec
대신 하는 이 sp_prepare
있습니다. 참고 사항을 참조하십시오 (** 자세한 내용은 하단에 있습니다.
내 테스트에 따르면 SqlCommand.Prepare()
호출 된 경우에도 (이 호출은 SQL Server에서 명령을 실행 하지 않음 ), ExecuteNonQuery
또는 ExecuteReader
다음에 나오는 것이 완전히 실행되며 ExecuteReader 인 경우 행을 반환합니다. 여전히 SQL Server 프로파일 러는 SqlCommand.Execute______()
호출 후 첫 번째 호출 SqlCommand.Prepare()
이 "Prepare SQL"이벤트로 .Execute___()
등록 되고 후속 호출이 "Exec Prepared SQL"이벤트로 등록됨을 보여줍니다.
테스트 코드
PasteBin ( http://pastebin.com/Yc2Tfvup) 에 업로드되었습니다 . 이 코드는 SQL Server 프로파일 러 추적이 실행되는 동안 (또는 확장 이벤트 세션) 실행되는 .NET / C # 콘솔 앱을 만듭니다. 각 단계 후에 일시 정지되므로 특정 명령문이 어떤 영향을 미치는지 명확하게됩니다.
최신 정보
더 많은 정보를 찾았으며을 (를) 호출하지 않는 약간의 잠재적 이유가 SqlCommand.Prepare()
있습니다. 테스트에서 주목 한 점은 해당 테스트 콘솔 앱을 실행하는 모든 사람에게 유의해야 할 사항입니다 sp_unprepare
. 명시적인 호출은 없습니다 . 나는 파고 들었고 MSDN 포럼에서 다음 게시물을 발견했습니다.
SqlCommand-준비 또는 준비하지 않습니까?
허용되는 답변에는 많은 정보가 포함되어 있지만 두드러진 점은 다음과 같습니다.
- ** 실제로 준비하는 것은 주로 쿼리 문자열을 유선으로 전송하는 데 걸리는 시간입니다.
- 준비된 쿼리는 캐시 된 계획의 저장을 보장하지 않으며 서버에 도달하면 임시 쿼리보다 빠르지 않습니다.
- RPC (CommandType.StoredProcedure)는 준비에서 아무것도 얻지 못합니다.
- 서버에서 준비된 핸들은 기본적으로 실행할 TSQL을 포함하는 메모리 내 맵에 대한 인덱스입니다.
- 맵은 연결별로 저장되며 교차 연결을 사용할 수 없습니다.
- 클라이언트가 풀에서 연결을 재사용 할 때 전송 된 재설정은 맵을 지 웁니다.
또한 SQLCAT 팀에서 다음과 같은 게시물을 발견했습니다. 관련 게시물은 ODBC 관련 문제 일 수 있지만 SqlClient는 SqlConnection을 폐기하면 올바르게 정리됩니다. SQLCAT 게시물에는 연결 풀 지우기 등과 같이 원인을 증명하는 데 도움이되는 추가 테스트가 언급되어 있지 않으므로 말하기가 어렵습니다.
준비된 SQL 문을 조심하십시오
결론
을 고려하면:
- 호출의 유일한 장점은
SqlCommand.Prepare()
네트워크를 통해 쿼리 텍스트를 다시 제출할 필요가없고,
- 연결 메모리 (예 : SQL Server 메모리)의 일부로 쿼리 텍스트 호출
sp_prepare
및 sp_prepexec
저장
나는 추천 에 대해 호출 SqlCommand.Prepare()
단점이 더 많은 서버 메모리를 복용하는 동안 유일한 잠재적 인 이점은 네트워크 패킷을 저장하기 때문이다. 대부분의 경우 소비되는 메모리의 양이 매우 적을 수 있지만 대부분의 DB 서버가 10 메가 비트 최소 (요즘 100 메가 비트 또는 기가비트) 연결을 통해 앱 서버에 직접 연결되므로 네트워크 대역폭은 거의 문제가되지 않습니다. 그리고 일부는 같은 상자에 있습니다 ;-). 그와 메모리는 거의 항상 네트워크 대역폭보다 더 적은 리소스입니다.
여러 데이터베이스에 연결할 수있는 소프트웨어를 작성하는 사람이라면 누구나 표준 인터페이스의 편리 성으로 인해이 비용 / 혜택 분석이 변경 될 수 있습니다. 그러나 그 경우에도 기본 객체를 제공한다는 점 에서 서로 다른 공급자 (따라서 호출 할 필요 가 없는 것과 같은 공급자 간)를 허용하는 "표준"DB 인터페이스를 추상화하는 것이 여전히 쉽다는 것을 믿어야합니다. Prepare()
앱 코드에서 이미 수행하고있는 지향적 인 프로그래밍 ;-).