First of all, I’d like to say ‘thanks’ to ‘adam machanic’. I don’t know his real name yet. His article named ‘SqlDataReader performance tips’ helped me a lot and I think that I should introduce his article to Korean developers. After this, I’m going to write in English. Once again, thank you, adam.
어제 ‘adam’이라는 개발자가 쓴 ‘SqlDataReader performance tips’라는 글을 읽고, 상당히 놀라운 사실을 알게 되었습니다. MSDN의 내용 중에 틀린 점이 있다는 것을 미리 밝히겠습니다. 아마 SqlDataReader에 대해 잘 알고 있다고 자신하고 있었더라고, 이 글을 읽어보는 편이 좋습니다. ‘adam’이 제시한 것 중 두 가지만 대충~ 해석(솔직히 베꼈습니다.)했습니다.
A) MSDN에도 나와 있는 내용이지만 Column의 이름보다는 Ordinal로 접근하는 편이 성능 향상에 도움이 됩니다.
while (reader.read()) object x = reader.GetValue(“ColX”); |
이나
while (reader.read()) object x = reader[“ColX”]; |
보다는 다음과 같은 코드가 좋습니다.
int ColX = reader.GetOrdinal(“ColX”); while (reader.read()) object x = reader[ColX]; |
실제로 Column 이름을 사용하면 내부적으로는 GetOrdinal 함수를 호출합니다. 루프 안에서 문자열로 데이터에 접근하는 경우에는 루프를 도는 횟수만큼 GetOrdinal 함수가 호출되는 것입니다.
B) 이 부분이 MSDN의 권고안과 다른 부분입니다. Get<datatype> (예. GetInt32)와 같은 함수보다는 static casts 를 사용하는 편이 낫습니다.
가장 나쁜 코드:
int x = reader.GetInt32(ColX); |
그나마 나은 코드:
int x = Convert.ToInt32(reader[ColX]); |
최선의 선택:
int x = (int)reader[ColX]; |
‘adam’은 총 세가지 제안을 하는데 제가 직접 테스트 코드를 작성하여 테스트한 것은 위의 두 가지 입니다. 거기에 더해 Connection Pooling과 Object Pooling의 성능 비교도 해봤습니다. 결론만 간단히 정리하자면 ‘adam’이 제시한 것이 맞습니다. 특히 많은 데이터를 자주 처리하는 경우에 그 진가가 나타납니다. 회사에 COM+로 Object Pooling을 구현해 놨습니다. 혹시나 하는 마음에 테스트를 해봤는데 결과가 좋아서 다행이었습니다. -_-
테스트를 그래프로 정리하면 좋을텐데 지금은 블로그 이전 작업 등등 해서 마음의 여유가 없습니다. 다만 테스트용으로 작성한 간단한 코드를 업로드합니다.
참고로 ADO.NET 코드의 성능 향상을 위해 다음 문서를 참고하십시오. 주옥 같은 문서입니다. ADO.NET 뿐만 아니라 .NET 어플리케이션의 성능 향상을 위한 지침입니다.
Improving .NET Application Performance and Scalability