다음 기사를 읽은 후 저자의 테스트가 ASP를 사용하는 친구들에게 정말 도움이 된다는 것을 알았습니다. ASP뿐만 아니라 다른 언어에서도 비슷할 것입니다. 서버에서 동적 콘텐츠를 생성하는 것은 ASP를 사용하는 주요 이유 중 하나이므로 우리가 선택한 첫 번째 테스트 프로젝트는 동적 콘텐츠를 응답 스트림으로 보내는 가장 좋은 방법을 결정하는 것이었습니다. 인라인 ASP 태그를 사용하는 것과 Response.Write 문을 사용하는 두 가지 기본 옵션(및 일부 변형)이 있습니다.
이러한 다양한 접근 방식을 테스트하기 위해 몇 가지 변수를 정의한 다음 이를 테이블에 삽입하는 간단한 ASP 페이지를 만들었습니다. 이 페이지는 간단하고 실용적이지 않지만 개별 문제를 격리하고 테스트하는 데는 충분합니다.
2.1 ASP 인라인 태그 사용
첫 번째 테스트는 ASP의 인라인 태그 <%= x %>를 사용하는 것입니다. 여기서 x는 변수입니다. 이는 사용하기 가장 편리한 방법이며 페이지의 HTML 부분을 더 쉽게 읽고 유지 관리할 수 있습니다.
다음과 같이 코드 코드를 복사합니다.
<% 옵션 명시적
희미한 이름
DimLastName
희미한 중간초기
희미한 주소
희미한 도시
희미한 상태
Dim전화번호
희미한 팩스 번호
희미한 이메일
희미한 생년월일
이름 = John
중간초기 = Q
성 = 공개
주소 = 100 Main Street
도시=뉴욕
주=NY
전화번호 = 1-212-555-1234
팩스번호 = 1-212-555-1234
이메일 = [email protected]
생년월일 = 1950년 1월 1일
%>
<HTML>
<헤드>
<TITLE>응답 테스트</TITLE>
</HEAD>
<본문>
<H1>응답 테스트</H1>
<표>
<tr><td><b>이름:</b></td><td><%= 이름 %></td></tr>
<tr><td><b>중간 이니셜:</b></td><td><%= 중간 이니셜 %></td></tr>
<tr><td><b>성:</b></td><td><%= 성 %></td></tr>
<tr><td><b>주소:</b></td><td><%= 주소 %></td></tr>
<tr><td><b>도시:</b></td><td><%= 도시 %></td></tr>
<tr><td><b>주:</b></td><td><%= 주 %></td></tr>
<tr><td><b>전화번호:</b></td><td><%= 전화번호 %></td></tr>
<tr><td><b>팩스 번호:</b></td><td><%= 팩스 번호 %></td></tr>
<tr><td><b>이메일:</b></td><td><%= 이메일 %></td></tr>
<tr><td><b>생년월일:</b></td><td><%= 생년월일 %></td></tr>
</TABLE>
</BODY>
</HTML>
/app1/response1.asp의 전체 코드
최고 기록 = 8.28ms/페이지
2.2 Response.Write를 사용하여 HTML 코드의 각 줄 출력
이전의 인라인 마크업 접근 방식은 컨텍스트 전환이라는 작업을 발생시키기 때문에 피해야 한다는 좋은 문헌이 많이 있습니다. 이 작업은 웹 서버에서 처리하는 코드 유형이 변경될 때(순수 HTML 전송에서 스크립트 처리로 또는 그 반대로) 발생하며, 이 전환에는 일정 시간이 걸립니다. 많은 프로그래머가 이것을 배운 후 첫 번째 반응은 Response.Write 함수를 사용하여 HTML 코드의 각 줄을 출력하는 것입니다.
다음과 같이 코드 코드를 복사합니다.
...
응답.쓰기(<html>)
응답.쓰기(<헤드>)
Response.Write( <title>응답 테스트</title>)
응답.쓰기(</head>)
응답.쓰기(<본문>)
Response.Write(<h1>응답 테스트</h1>)
응답.쓰기(<테이블>)
Response.Write(<tr><td><b>이름:</b></td><td> & 이름 & </td></tr>)
Response.Write(<tr><td><b>중간 이니셜:</b></td><td> & MiddleInitial & </td></tr>)
...
/app1/response2.asp 조각
최고 기록 = 8.28ms/페이지
응답 시간 = 8.08ms/페이지
차이 = -0.20ms(2.4% 감소)
인라인 마크업 버전에 비해 우리가 본 성능 향상은 너무 작아서 놀라웠습니다. 이는 페이지에 더 많은 함수 호출이 있기 때문일 수 있습니다. 그러나 이 방법은 더 큰 단점이 있는데, HTML 코드가 함수에 내장되어 있기 때문에 스크립트 코드가 너무 길어지고 읽기 및 유지 관리가 불편해진다.
2.3 래퍼 함수 사용
Response.Write는 텍스트 줄 끝에 CRLF(Carriage Return - Line Feed, Carriage Return - Line Feed)를 추가하지 않습니다. 이는 위 방법을 사용할 때 가장 아쉬운 점입니다. HTML 코드가 서버 측에서 형식이 잘 지정되어 있더라도 브라우저에 표시되는 내용은 여전히 한 줄의 긴 코드일 뿐입니다. 하지만 이 문제가 유일한 실망은 아니었습니다. 사람들은 곧 CRLF를 자동으로 추가할 수 있는 Response.WriteLn 함수가 없다는 사실을 발견했습니다. 자연스러운 반응은 Response.Write에 대한 래퍼 함수를 만들고 각 줄 뒤에 CRLF를 추가하는 것입니다.
...
writeCR(<tr><td><b>이름:</b></td><td> & 이름 & </td></tr>)
...
SUB 쓰기CR(str)
응답.쓰기(str & vbCRLF)
끝부분
/app1/response4.asp 조각
최고 기록 = 8.08ms/페이지
응답 시간 = 10.11ms/페이지
차이 = +2.03ms(25.1% 증가)
결과적으로 성능이 크게 저하됩니다. 물론 이는 주로 이 방법이 함수 호출 횟수를 두 배로 늘리고 성능에 미치는 영향이 매우 명백하기 때문입니다. 이 사용은 무슨 수를 써서라도 피해야 합니다. CRLF는 각 줄 끝에 2바이트의 추가 바이트를 생성하며, 이 2바이트는 브라우저가 페이지를 표시하는 데 쓸모가 없습니다. 대부분의 경우, 브라우저 측 HTML 코드의 아름다운 형식은 경쟁업체가 페이지 디자인을 더 쉽게 읽고 이해할 수 있도록 해줍니다.
2.4 여러 응답 병합.쓰기
함수 캡슐화에 대한 마지막 테스트를 무시하고 다음 논리적 단계는 별도의 Response.Write 문의 모든 문자열을 하나의 명령문으로 병합하여 함수 호출 수를 줄이고 코드 효율성을 높이는 것입니다.
다음과 같이 코드 코드를 복사합니다.
응답.쓰기(<html> & _
<머리> & _
<title>응답 테스트</title> & _
</head> & _
<본문> & _
<h1>응답 테스트</h1> & _
<테이블> & _
<tr><td><b>이름:</b></td><td> & 이름 & </td></tr> & _
...
<tr><td><b>생년월일:</b></td><td> & 생년월일 & </td></tr> & _
</테이블> & _
</body> & _
</html>)
/app1/response3.asp 조각
최고 기록 = 8.08ms/페이지
응답 시간 = 7.05ms/페이지
차이 = -1.03ms(12.7% 감소)
이것이 단연 가장 좋은 방법입니다.
2.5 여러 Response.Write를 결합하고 각 줄 끝에 CRLF를 추가합니다.
어떤 사람들은 HTML 코드가 브라우저 측에서 아름답게 보이는지에 대해 매우 염려하므로 vbCRLF 상수를 사용하여 HTML 코드의 각 줄 끝에 캐리지 리턴을 추가합니다. 다른 테스트 코드는 위의 예와 동일합니다. .
...
응답.쓰기(<html> & vbCRLF & _
<헤드> & vbCRLF & _
<title>응답 테스트</title> & vbCRLF & _
</head> & vbCRLF & _
...
/app1/response5.asp 조각
최고 기록 = 7.05ms/페이지
응답 시간 = 7.63ms/페이지
차이 = +0.58ms(8.5% 증가)
결과적으로 문자열 연결 작업이 추가되고 출력 텍스트가 늘어나서 성능이 약간 저하됩니다.
2.6 코멘트
위의 ASP 출력 테스트 결과를 바탕으로 다음과 같은 인코딩 규칙을 도출했습니다.
임베디드 ASP를 너무 많이 사용하지 마십시오.
가능한 한 많은 Response.Write 문을 단일 문으로 결합합니다.
CRLF를 추가하기 위해 Response.Write를 캡슐화하지 마십시오.
HTML 출력 형식을 지정하려면 Response.Write 문 바로 뒤에 CRLF를 추가하세요.
개요: ASP에서 동적으로 생성된 콘텐츠를 출력하는 가장 효율적인 방법은 무엇입니까? 데이터베이스 레코드세트를 추출하는 가장 좋은 방법은 무엇입니까? 이 기사에서는 이러한 ASP 개발에서 발생하는 거의 20가지 일반적인 문제를 테스트합니다. 테스트 도구에 표시되는 시간은 일반적으로 당연하게 여겨지는 이러한 문제는 주목할 가치가 있을 뿐만 아니라 그 안에 예상치 못한 비밀이 숨겨져 있음을 알려줍니다.
1. 테스트 목적
이 기사의 첫 번째 부분에서는 ASP 개발의 몇 가지 기본 문제를 조사하고 페이지에 배치된 코드가 성능에 어떤 영향을 미치는지 독자가 이해하는 데 도움이 되는 몇 가지 성능 테스트 결과를 제공합니다. ADO는 Microsoft에서 개발한 보편적이고 사용하기 쉬운 데이터베이스 인터페이스입니다. ADO를 통해 데이터베이스와 상호 작용하는 것은 ASP의 가장 중요한 응용 프로그램 중 하나입니다.
ADO가 제공하는 기능은 매우 광범위하므로 이 기사를 준비할 때 가장 큰 어려움은 문제의 범위를 정의하는 방법입니다. 많은 양의 데이터를 추출하면 웹 서버의 부하가 크게 증가할 수 있다는 점을 고려하여 ADO 레코드 세트를 운영하기 위한 최적의 구성이 무엇인지 알아보는 것이 이 섹션의 주요 목적이라고 결정했습니다. 그러나 문제의 범위를 좁혀도 여전히 큰 어려움에 직면합니다. ADO는 동일한 작업을 완료하는 데에도 다양한 방법이 있을 수 있기 때문입니다. 예를 들어 레코드세트는 Recordset 클래스뿐만 아니라 Connection 및 Command 클래스를 통해서도 추출할 수 있으며, 레코드세트 개체를 얻은 후에도 성능에 큰 영향을 미칠 수 있는 작업 방법이 많이 있습니다. 그러나 1부에서와 마찬가지로 가능한 가장 광범위한 문제를 다루려고 노력할 것입니다.
특히 이 섹션의 목표는 다음 질문에 대답하기에 충분한 정보를 수집하는 것입니다.
ADOVBS.inc는 포함을 통해 참조되어야 합니까?
l레코드세트를 사용할 때 별도의 연결 개체를 만들어야 합니까?
l레코드세트를 추출하는 가장 좋은 방법은 무엇입니까?
l가장 효율적인 커서 유형과 레코드 잠금 방법은 무엇입니까?
l로컬 레코드 세트를 사용해야 합니까?
l레코드세트 속성을 설정하는 가장 좋은 방법은 무엇입니까?
l레코드 세트의 필드 값을 참조하는 데 가장 효율적인 방법은 무엇입니까?
l임시 문자열로 출력을 수집하는 좋은 방법인가요?
2. 테스트 환경
이번 테스트에는 총 21개의 ASP 파일이 사용되었으며, 이 문서의 뒷부분에서 다운로드할 수 있습니다. 각 페이지는 각각 0, 25, 250개의 레코드를 반환하는 세 가지 다른 쿼리를 실행하도록 설정됩니다. 이는 레코드세트를 반복하는 오버헤드로부터 페이지 자체의 초기화 및 실행 오버헤드를 분리하는 데 도움이 됩니다.
테스트를 용이하게 하기 위해 데이터베이스 연결 문자열과 SQL 명령 문자열이 Global.asa에 응용 프로그램 변수로 저장됩니다. 테스트 데이터베이스는 SQL Server 7.0이므로 연결 문자열은 OLEDB를 연결 공급자로 지정하고 테스트 데이터는 SQL Server의 Northwind 데이터베이스에서 가져옵니다. SQL SELECT 명령은 NorthWind Orders 테이블에서 지정된 7개의 필드를 추출합니다.
다음과 같이 코드 코드를 복사합니다.
<SCRIPT LANGUAGE=VBScript RUNAT=서버>
하위 애플리케이션_OnStart
애플리케이션(Conn) = 공급자=SQLOLEDB & _
서버=내서버 & _
uid=sa & _
비밀번호=;
데이터베이스=북풍
애플리케이션(SQL) = SELECTTOP 0OrderID, & _
고객 ID, & _
직원ID, & _
주문 날짜, & _
필수날짜, & _
배송 날짜, & _
화물 & _
FROM[주문]
서브 끝
</SCRIPT>
'대체 SQL - 25개 레코드
애플리케이션(SQL) = SELECTTOP 25OrderID, & _
고객 ID, & _
직원ID, & _
주문 날짜, & _
필수날짜, & _
배송 날짜, & _
화물 & _
FROM[주문]
'대체 SQL-250 레코드
애플리케이션(SQL) = SELECTTOP 250 OrderID, & _
고객 ID, & _
직원ID, & _
주문 날짜, & _
필수날짜, & _
배송 날짜, & _
화물 & _
FROM[주문]
테스트 서버 구성은 450Mhz Pentium, 512MB RAM, NT Server 4.0 SP5, MDAC 2.1(Data Access Component) 및 Microsoft Scripting Engine 버전 5.0이었습니다. SQL Server가 유사한 구성을 가진 다른 컴퓨터에서 실행되고 있습니다. 첫 번째 부분에서와 마찬가지로 Microsoft 웹 애플리케이션 스트레스 도구를 사용하여 첫 번째 페이지 요청부터 서버에서 수신된 마지막 바이트(TTLB, Time To Last Byte)까지의 시간을 기록합니다. 시간은 밀리초 단위입니다. 테스트 스크립트는 각 페이지를 1300회 이상 호출했으며 실행하는 데 약 20시간이 걸렸습니다. 아래 표시된 시간은 세션의 평균 TTLB입니다. 첫 번째 부분에서와 같이 우리는 코드의 확장성이나 서버 성능이 아닌 코드의 효율성에만 관심이 있다는 것을 기억하십시오.
또한 서버 버퍼링을 활성화했습니다. 또한 모든 파일 이름을 동일한 길이로 만들기 위해 일부 파일 이름에는 하나 이상의 밑줄이 포함되어 있습니다.
3. 첫 번째 테스트
첫 번째 테스트에서는 Microsoft ASP ADO 샘플에서 발견된 일반적인 시나리오를 시뮬레이션하는 레코드 세트를 추출했습니다. 이 예(ADO__01.asp)에서는 먼저 연결을 연 다음 레코드 집합 개체를 만듭니다. 물론 여기의 스크립트는 이 기사의 첫 번째 부분에 요약된 코딩 규칙에 따라 최적화되었습니다.
다음과 같이 코드 코드를 복사합니다.
<% 옵션 명시적 %>
<!-- #포함 파일=ADOVBS.INC -->
<%
희미한 objConn
희미한 물체RS
응답.쓰기(_
<HTML><HEAD> & _
<TITLE>ADO 테스트</TITLE> & _
</HEAD><BODY> _
)
objConn = Server.CreateObject(ADODB.Connection) 설정
objConn.응용 프로그램 열기(Conn)
objRS 설정 = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = adOpenForwardOnly
objRS.LockType = adLockReadOnly
objRS.애플리케이션 열기(SQL)
objRS.EOF이면
응답.쓰기(기록을 찾을 수 없음)
또 다른
'제목을 쓴다
응답.쓰기(_
<테이블 테두리=1> & _
<TR> & _
<TH>주문 ID</TH> & _
<TH>고객ID</TH> & _
<TH>직원ID</TH> & _
<TH>주문 날짜</TH> & _
<TH>필수 날짜</TH> & _
<TH>배송일</TH> & _
<TH>화물</TH> & _
</TR> _
)
'데이터 쓰기
objRS.EOF가 아닌 동안 수행
응답.쓰기(_
<TR> & _
<TD> & objRS(주문ID) & </TD> & _
<TD> & objRS(고객ID) & </TD> & _
<TD> & objRS(직원ID) & </TD> & _
<TD> & objRS(주문 날짜) & </TD> & _
<TD> & objRS(필수 날짜) & </TD> & _
<TD> & objRS(배송일) & </TD> & _
<TD> & objRS(화물) & </TD> & _
</TR> _
)
objRS.MoveNext
고리
응답.쓰기(</TABLE>)
종료 조건
objRS.닫기
objConn.닫기
objRS = 없음 설정
objConn = 없음 설정
응답.쓰기(</BODY></HTML>)
%>
테스트 결과는 다음과 같습니다.
각 열에 있는 숫자의 의미를 살펴보겠습니다.
0은 0개 레코드의 페이지에 필요한 TTLB(밀리초)를 반환합니다. 모든 테스트에서 이 값은 레코드 세트 데이터를 반복하는 시간을 제외하고 페이지 자체를 생성하는 시간 오버헤드(개체 생성 포함)로 간주됩니다.
25개 레코드를 가져오고 표시하는 데 밀리초당 25TTLB
tot time/2525 열의 TTLB는 25로 나누어지며, 이는 레코드당 총 평균 시간 비용입니다.
disp time/2525 TTLB 열에서 0 열 TTLB를 뺀 다음 25로 나눕니다. 이 값은 레코드세트를 반복하면서 단일 레코드를 표시하는 데 필요한 시간을 반영합니다.
250 250개 레코드의 TTLB를 추출하여 표시합니다.
총 시간/250250 열의 TTLB는 25로 나뉩니다. 이 값은 단일 레코드의 총 평균 시간 비용을 나타냅니다.
disp time/250 열 250의 TTLB를 열 0의 TTLB에서 뺀 다음 250으로 나눕니다. 이 값은 레코드세트를 반복하면서 단일 레코드를 표시하는 데 필요한 시간을 반영합니다.
위의 테스트 결과는 다음 테스트 결과와 비교하는 데 사용됩니다.
4. ADOVBS.inc를 포함하여 참조해야 합니까?
Microsoft에서 제공하는 ADOVBS.inc에는 대부분의 ADO 속성 상수를 정의하는 270줄의 코드가 포함되어 있습니다. 우리의 예에서는 ADOVBS.inc의 상수 2개만 참조합니다. 따라서 이번 테스트(ADO__02.asp)에서는 포함된 파일 참조를 삭제하고 속성 설정 시 해당 값을 직접 사용했습니다.
objRS.CursorType = 0?'
objRS.LockType = 1' adLockReadOnly
페이지 오버헤드가 23% 감소한 것을 확인할 수 있습니다. 이 값은 개별 레코드의 가져오기 및 표시 시간에 영향을 주지 않습니다. 여기에서 변경한 사항은 루프 내의 레코드 세트 작업에 영향을 주지 않기 때문입니다. ADOVBS.inc 참조 문제를 해결하는 방법에는 여러 가지가 있습니다. ADOVBS.inc 파일을 참조로 사용하고 설명을 통해 설정을 설명하는 것이 좋습니다. Part 1에서 언급했듯이 주석을 적당히 사용하면 코드 효율성에 최소한의 영향을 미칩니다. 또 다른 방법은 ADOVBS.inc 파일에서 필요한 상수를 페이지에 복사하는 것입니다.
이 문제를 해결하는 좋은 방법도 있습니다. 즉, ADO 형식 라이브러리에 연결하여 모든 ADO 상수를 직접 사용할 수 있도록 만드는 것입니다. 모든 ADO 상수에 직접 액세스하려면 Global.asa 파일에 다음 코드를 추가하세요.
<!--메타데이터 유형=typelib
파일=C:프로그램 파일공통 파일SYSTEMADOmsado15.dll
NAME=ADODB 유형 라이브러리 -->
또는:
<!--메타데이터 유형=typelib
UUID=00000205-0000-0010-8000-00AA006D2EA4
NAME=ADODB 유형 라이브러리 -->
따라서 첫 번째 규칙은 다음과 같습니다.
lADOVBS.inc 파일을 포함하지 말고 다른 방법을 통해 ADO 상수에 액세스하고 사용하십시오.
5. 레코드세트를 사용할 때 별도의 연결 개체를 만들어야 합니까?
이 질문에 올바르게 대답하려면 두 가지 다른 조건에서 테스트를 분석해야 합니다. 첫째, 페이지에 단 하나의 데이터베이스 트랜잭션이 있고, 둘째, 페이지에 여러 데이터베이스 트랜잭션이 있습니다.
이전 예에서는 별도의 Connection 개체를 만들어 Recordset의 ActiveConnection 속성에 할당했습니다. 그러나 ADO__03.asp에 표시된 것처럼 연결 문자열을 ActiveConnection 속성에 직접 할당하여 스크립트에서 연결 개체를 초기화하고 구성하는 추가 단계를 제거할 수도 있습니다.
objRS.ActiveConnection = 애플리케이션(Conn)
Recordset 개체는 여전히 연결을 생성해야 하지만 이때 생성은 고도로 최적화된 조건에서 수행됩니다. 그 결과, 이전 테스트에 비해 페이지 오버헤드가 23% 더 감소했고, 예상대로 단일 레코드의 표시 시간도 크게 변하지 않았습니다.
따라서 두 번째 규칙은 다음과 같습니다.
l하나의 레코드 집합만 사용하는 경우 연결 문자열을 ActiveConnection 속성에 직접 할당합니다.
다음으로 페이지에서 여러 레코드 세트를 사용할 때 위의 규칙이 여전히 유효한지 확인합니다. 이 상황을 테스트하기 위해 FOR 루프를 도입하여 이전 예제를 10번 반복합니다. 이 테스트에서는 세 가지 변형을 살펴보겠습니다.
먼저 ADO__04.asp에 표시된 대로 각 루프에서 Connection 개체가 설정되고 삭제됩니다.
다음과 같이 코드 코드를 복사합니다.
나는 어둡다
i = 1 ~ 10의 경우
objConn = Server.CreateObject(ADODB.Connection) 설정
objConn.응용 프로그램 열기(Conn)
objRS 설정 = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.애플리케이션 열기(SQL)
objRS.EOF이면
응답.쓰기(기록을 찾을 수 없음)
또 다른
'제목을 쓴다
...
'데이터 쓰기
...
종료 조건
objRS.닫기
objRS = 없음 설정
objConn.닫기
objConn = 없음 설정
다음
둘째, ADO__05.asp에 표시된 대로 루프 외부에 연결 개체를 만들고 이 개체를 모든 레코드 집합과 공유합니다.
다음과 같이 코드 코드를 복사합니다.
objConn = Server.CreateObject(ADODB.Connection) 설정
objConn.응용 프로그램 열기(Conn)
나는 어둡다
i = 1 ~ 10의 경우
objRS 설정 = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.애플리케이션 열기(SQL)
objRS.EOF이면
응답.쓰기(기록을 찾을 수 없음)
또 다른
'제목을 쓴다
...
'데이터 쓰기
...
종료 조건
objRS.닫기
objRS = 없음 설정
다음
objConn.닫기
objConn = 없음 설정
셋째, ADO__06.asp에 표시된 대로 각 루프의 ActiveConnection 속성에 연결 문자열을 할당합니다.
다음과 같이 코드 코드를 복사합니다.
나는 어둡다
i = 1 ~ 10의 경우
objRS 설정 = Server.CreateObject(ADODB.Recordset)
objRS.ActiveConnection = 애플리케이션(Conn)
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.애플리케이션 열기(SQL)
objRS.EOF이면
응답.쓰기(기록을 찾을 수 없음)
또 다른
'제목을 쓴다
...
'데이터 쓰기
...
종료 조건
objRS.닫기
objRS = 없음 설정
다음
짐작할 수 있듯이 루프 내에서 연결 개체를 만들고 해제하는 것은 가장 효율적인 방법입니다. 그러나 놀랍게도 루프 내의 ActiveConnection 속성에 연결 문자열을 직접 할당하는 것은 단일 연결 개체를 공유하는 것보다 약간 느릴 뿐입니다.
그럼에도 불구하고 세 번째 규칙은 다음과 같아야 합니다.
l동일한 페이지에서 여러 레코드 세트가 사용되는 경우 단일 연결 개체를 생성하고 ActiveConnection 속성을 통해 공유합니다.
6. 어떤 커서 유형과 기록 잠금 방법이 가장 효율적입니까?
지금까지 모든 테스트에서 우리는 레코드 세트에 액세스하기 위해 앞으로 전용 커서만 사용했습니다. 레코드 세트에 대해 ADO에서 제공하는 커서에는 정적 스크롤 가능 커서, 동적 스크롤 가능 커서 및 키 세트 커서의 세 가지 유형이 있습니다. 각 커서는 이전 레코드와 다음 레코드에 액세스하고 다른 프로그램에서 데이터 수정 사항을 볼 수 있는지 여부 등 다양한 기능을 제공합니다. 그러나 각 커서 유형의 기능에 대한 자세한 설명은 이 기사의 범위를 벗어납니다. 다음 표는 다양한 커서 유형을 비교 분석한 것입니다.
다른 모든 커서 유형에는 정방향 전용 커서에 비해 추가 오버헤드가 필요하며 이러한 커서는 일반적으로 루프 내에서 속도가 더 느립니다. 따라서 우리는 다음과 같은 주의 사항을 공유하고 싶습니다. 이렇게 생각하지 마십시오. 글쎄요, 때로는 동적 커서를 사용할 것이므로 항상 이 커서를 사용할 것입니다.
기록 잠금 방법 선택에도 동일한 감정이 적용됩니다. 이전 테스트에서는 읽기 전용 잠금 방법만 사용했지만 보수적, 개방형, 개방형 일괄 처리라는 세 가지 다른 방법이 있습니다. 커서 유형과 마찬가지로 이러한 잠금 방법은 레코드 세트 데이터 작업에 대한 다양한 기능과 제어 기능을 제공합니다.
우리는 다음과 같은 규칙에 도달했습니다.
l작업에 적합한 가장 간단한 커서 유형과 기록 잠금 방법을 사용하십시오.
7. 레코드 세트를 추출하는 데 사용하는 가장 좋은 방법은 무엇입니까?
지금까지는 Recordset 개체를 생성하여 레코드 집합을 추출해 왔지만 ADO는 간접적인 레코드 집합 추출 방법도 제공합니다. 다음 테스트에서는 ADO__03.asp와 연결 개체(CONN_01.asp)에서 직접 레코드 집합을 만드는 방법을 비교합니다.
다음과 같이 코드 코드를 복사합니다.
objConn = Server.CreateObject(ADODB.Connection) 설정
objConn.응용 프로그램 열기(Conn)
objRS 설정 = objConn.Execute(Application(SQL))
페이지 오버헤드가 약간 증가했으며 단일 레코드의 표시 시간은 변경되지 않은 것을 확인할 수 있습니다.
Command 개체에서 직접 레코드 집합 개체(CMD__02.asp)를 만드는 방법을 살펴보겠습니다.
다음과 같이 코드 코드를 복사합니다.
objCmd = Server.CreateObject(ADODB.Command) 설정
objCmd.ActiveConnection = 애플리케이션(Conn)
objCmd.CommandText = 애플리케이션(SQL)
objRS = objCmd.Execute 설정
마찬가지로, 단일 레코드의 표시 시간에 큰 변화가 없이 페이지 오버헤드가 약간 증가합니다. 후자의 두 방법의 성능 차이는 작지만 고려해야 할 중요한 문제가 있습니다.
Recordset 클래스를 통해 레코드세트를 만들 때 가장 유연하게 레코드세트의 처리를 제어할 수 있습니다. 후자의 두 가지 방법은 압도적인 성능을 달성하지 못하기 때문에 기본적으로 반환되는 커서 유형과 레코드 잠금 방법을 주로 고려합니다. 어떤 경우에는 기본값이 가장 이상적인 것은 아닙니다.
따라서 후자의 두 가지 방법 중 하나를 선택해야 하는 특별한 이유가 없는 한 다음 규칙을 고려하는 것이 좋습니다.
l 최고의 성능과 유연성을 얻으려면 ADODB.Recordset 클래스를 통해 레코드 세트를 인스턴스화합니다.
8. 로컬 레코드세트를 사용해야 합니까?
ADO는 로컬(클라이언트) 레코드 세트의 사용을 허용합니다. 이때 쿼리는 쿼리가 완료된 후 연결을 즉시 닫을 수 있으며 로컬 커서를 사용하여 데이터에 액세스할 수 있습니다. 연결을 해제하는 데 편리함을 가져다주는 미래. 로컬 레코드 집합을 사용하는 것은 데이터를 오프라인으로 사용해야 하는 원격 데이터 서비스에 액세스하는 데 중요하지만 일반 응용 프로그램에도 도움이 될까요?
다음으로 CursorLocation 특성을 추가하고 레코드 세트를 연 후 연결(CLIENT1.asp)을 닫습니다.
다음과 같이 코드 코드를 복사합니다.
objRS 설정 = Server.CreateObject(ADODB.Recordset)
objRS.CursorLocation = 2' adUseClient
objRS.ActiveConnection = 애플리케이션(Conn)
objRS.LockType = 1?'
objRS.애플리케이션 열기(SQL)
objRS.ActiveConnection = 없음
이론적으로 이 접근 방식은 두 가지 이유로 효율성에 도움이 됩니다. 첫째, 레코드 간 이동 시 연결을 통해 반복적으로 데이터를 요청하는 것을 방지하고, 둘째, 리소스 요구 사항을 완화합니다. 그러나 위의 표를 보면 로컬 레코드 집합을 사용하는 것이 효율성 향상에 전혀 도움이 되지 않는 것으로 보입니다. 이는 로컬 레코드 집합을 사용할 때 프로그램 설정에 관계없이 커서가 항상 정적 유형이 되기 때문일 수 있습니다.
규칙 6은 다음과 같습니다.
l레코드 세트의 지역화가 꼭 필요한 경우가 아니면 이는 피해야 합니다.
10. 레코드 세트의 필드 값을 참조하는 데 가장 효율적인 방법은 무엇입니까?
10.1 테스트
지금까지 우리는 레코드세트의 필드 값을 이름으로 참조해 왔습니다. 이 방법은 매번 해당 필드를 찾아야 하므로 그다지 효율적이지 않습니다. 이를 입증하기 위해 다음 테스트에서는 컬렉션(ADO__08.asp)의 인덱스로 필드 값을 참조합니다.
다음과 같이 코드 코드를 복사합니다.
'데이터 쓰기
objRS.EOF가 아닌 동안 수행
응답.쓰기(_
<TR> & _
<TD> & objRS(0) & </TD> & _
<TD> & objRS(1) & </TD> & _
<TD> & objRS(2) & </TD> & _
<TD> & objRS(3) & </TD> & _
<TD> & objRS(4) & </TD> & _
<TD> & objRS(5) & </TD> & _
<TD> & objRS(6) & </TD> & _
</TR> _
)
objRS.MoveNext
고리
예상한 대로 페이지 오버헤드에도 약간의 변화가 있습니다(아마도 약간의 코드 감소로 인해). 그러나 이 접근 방식을 사용하면 표시 시간이 상당히 향상됩니다.
다음 테스트에서는 모든 필드를 변수에 개별적으로 바인딩합니다(ADO__09.asp).
다음과 같이 코드 코드를 복사합니다.
objRS.EOF이면
응답.쓰기(기록을 찾을 수 없음)
또 다른
'제목을 쓴다
...
희미한 fld0
희미한 fld1
희미한 fld2
희미한 fld3
희미한 fld4
희미한 fld5
희미한 fld6
fld0 = objRS(0) 설정
fld1 = objRS(1) 설정
fld2 = objRS(2) 설정
fld3 = objRS(3) 설정
fld4 = objRS(4) 설정
fld5 = objRS(5) 설정
fld6 = objRS(6) 설정
'데이터 쓰기
objRS.EOF가 아닌 동안 수행
응답.쓰기(_
<TR> & _
<TD> & fld0 & </TD> & _
<TD> & fld1 & </TD> & _
<TD> & fld2 & </TD> & _
<TD> & fld3 & </TD> & _
<TD> & fld4 & </TD> & _
<TD> & fld5 & </TD> & _
<TD> & fld6 & </TD> & _
</TR> _
)
objRS.MoveNext
고리
fld0 = 없음으로 설정
fld1 = 없음으로 설정
fld2 = 없음으로 설정
fld3 = 없음으로 설정
fld4 = 없음으로 설정
fld5 = 없음 설정
fld6 = 없음으로 설정
응답.쓰기(</TABLE>)
종료 조건
이는 지금까지 최고 기록이다. 단일 레코드의 표시 시간이 0.45밀리초 미만으로 단축되었습니다.
위의 스크립트에는 모두 결과 레코드 세트의 구성에 대한 어느 정도의 이해가 필요합니다. 예를 들어 열 머리글에서 직접 필드 이름을 사용하여 각 필드 값을 개별적으로 참조합니다. 다음 테스트에서는 필드 컬렉션을 탐색하여 필드 데이터를 얻을 뿐만 아니라 필드 제목도 동일한 방식으로 얻습니다(ADO__10.asp).
다음과 같이 코드 코드를 복사합니다.
objRS.EOF이면
응답.쓰기(기록 없음)
또 다른
'제목 쓰기 Response.Write(<TABLE BORDER=1><TR>)
objRS.Fields의 각 objFld에 대해
응답.쓰기(<TH> & objFld.name & </TH>)
다음
응답.쓰기(</TR>)
'데이터 쓰기
objRS.EOF가 아닌 동안 수행
응답.쓰기(<TR>)
objRS.Fields의 각 objFld에 대해
?응답.쓰기(<TD> & objFld.value & </TD>)
다음
응답.쓰기(</TR>)
objRS.MoveNext
고리
응답.쓰기(</TABLE>)
종료 조건
보시다시피 코드 성능은 감소했지만 여전히 ADO__07.asp보다 빠릅니다.
다음 테스트 예는 이전 두 가지 방법을 절충한 것입니다. 우리는 동적으로 할당된 배열에 필드 참조를 저장하여 성능을 향상시키면서 동적 기능을 계속 유지할 것입니다.
다음과 같이 코드 코드를 복사합니다.
objRS.EOF이면
응답.쓰기(기록을 찾을 수 없음)
또 다른
Dim fldCount
fldCount = objRS.Fields.Count
희미한 필드()
ReDim fld(fldCount)
나는 어둡다
i = 0에서 fldCount-1까지
fld(i) = objRS(i) 설정
다음
'제목을 쓴다
Response.Write(<TABLE BORDER=1><TR>) i = 0에서 fldCount-1까지
응답.쓰기(<TH> & fld(i).name & </TH>)
다음
응답.쓰기(</TR>)
'데이터 쓰기
objRS.EOF가 아닌 동안 수행
응답.쓰기(<TR>)
i = 0에서 fldCount-1까지
응답.쓰기(<TD> & fld(i) & </TD>)
다음
응답.쓰기(</TR>)
objRS.MoveNext
고리
i = 0에서 fldCount-1까지
fld(i) = 아무것도 설정하지 않음
다음
응답.쓰기(</TABLE>)
종료 조건
이전 최고 수준을 능가하지는 못하지만 처음 몇 가지 예보다 빠르며 모든 레코드 집합을 동적으로 처리할 수 있다는 장점이 있습니다.
이전 테스트 코드와 비교하여 다음 테스트 코드는 근본적으로 변경되었습니다. Recordset 자체에 직접 액세스하는 대신 Recordset 개체의 GetRows 메서드를 사용하여 데이터 반복을 위한 배열을 채웁니다. GetRows를 호출한 후 즉시 Recordset이 Nothing으로 설정됩니다. 이는 시스템 리소스가 가능한 한 빨리 해제된다는 의미입니다. 또한 배열의 첫 번째 차원은 필드를 나타내고 두 번째 차원은 행(ADO__12.asp)을 나타냅니다.
다음과 같이 코드 코드를 복사합니다.
objRS.EOF이면
응답.쓰기(기록을 찾을 수 없음)
objRS.닫기
objRS = 없음 설정
또 다른
'제목을 쓴다
...
'배열 설정
어두컴컴한 도착RS
arrRS = objRS.GetRows
'레코드세트를 일찍 닫습니다.
objRS.닫기
objRS = 없음 설정
'데이터 쓰기
DimnumRows
DimnumFlds
희미한 행
희미한 필드
numFlds = 유바운드(arrRS, 1)
numRows = 유바운드(arrRS, 2)
행= 0 ~ numRows
응답.쓰기(<TR>)
fld = 0 ~ numFlds의 경우
Response.Write(<TD> & arrRS(fld, 행) & </TD>)
다음
응답.쓰기(</TR>)
다음
응답.쓰기(</TABLE>)
종료 조건
GetRows 메서드를 사용하면 전체 레코드 집합이 배열로 추출됩니다. 레코드 세트가 매우 큰 경우 리소스 문제가 발생할 수 있지만 MoveNext 및 EOF 확인과 같은 함수 호출이 취소되므로 루프에서 데이터에 액세스하는 것이 실제로 더 빠릅니다.
속도에는 비용이 따르므로 이제 레코드 세트의 메타데이터가 손실됩니다. 이 문제를 해결하기 위해 GetRows를 호출하기 전에 레코드 세트 개체에서 헤더 정보를 추출할 수 있으며, 데이터 유형 및 기타 정보도 미리 추출할 수 있습니다. 또한 테스트의 성능 이점은 레코드 세트가 더 클 때만 발생한다는 점에 유의하십시오.
이 세트의 마지막 테스트에서는 레코드 세트의 GetString 메서드를 사용합니다. GetString 메서드는 전체 레코드 집합을 큰 문자열로 추출하고 구분 기호(ADO__13.asp)를 지정할 수 있도록 합니다.
다음과 같이 코드 코드를 복사합니다.
objRS.EOF이면
응답.쓰기(기록 없음)
objRS.닫기
objRS = 없음 설정
또 다른
'제목을 쓴다
...
'배열 설정
희미한 strTable
strTable = objRS.GetString (2, , </TD><TD>, </TD></TR><TR><TD>)
'레코드세트를 일찍 닫습니다.
objRS.닫기
objRS = 없음 설정
Response.Write(strTable & </TD></TR></TABLE>)
종료 조건