프로그래밍/ASP.NET

Linq string 쿼리와 var 쿼리 성능비교

Doonee 2017. 1. 22. 19:28
반응형

똑같은 MS SQL DB 테이블을 호출하는 쿼리로 성능비교를 해보았다. 전체 row의 갯수는 1,100만개

SELECT *
FROM [dbo].[BIG_DATA_TEST]
WHERE NUM <= [갯수를 변경하면서...] 

string 쿼리와 var 쿼리는 아래와 같다.

             strQuery = string.Format(@"
                SELECT *
                FROM [dbo].[BIG_DATA_TEST]
                WHERE NUM <= [갯수변경]
            ");

            Response.Write("<br>list 생성 전 : " + sw.Elapsed.Seconds.ToString() + " 초 지연 되었습니다.<br>");
           
            List<BIG_DATA_TEST_ENTITY> list = db.Database.SqlQuery<BIG_DATA_TEST_ENTITY>(strQuery).ToList();

            Response.Write("<br>list 생성 후 : " + sw.Elapsed.Seconds.ToString() + " 초 지연 되었습니다.<br>");
           
            if (list != null && list.Count > 0)
            {
                Response.Write("<br>list.Count 추출 후 : " + sw.Elapsed.Seconds.ToString() + " 초 지연 되었습니다.<br>");

                int i = 0;
                foreach (var item in list)
                {
                    if (i != 0 && i % 10000 == 0) //1만번째 마다
                    {
                        Response.Write("<br>" + i.ToString("###,###") + " : " + sw.Elapsed.Seconds.ToString() + " 초 지연 되었습니다.<br>");
                    }
                    i++;    
                }
            } 
 

 


            connectionMethod = "linq with var query";
           
            Response.Write("<br>vQuery 생성 전 : " + sw.Elapsed.Seconds.ToString() + " 초 지연 되었습니다.<br>");
           
            var vQuery = from b in db.BIG_DATA_TEST where b.NUM <= [갯수변경] select b;
           
            Response.Write("<br>vQuery 생성 후 : " + sw.Elapsed.Seconds.ToString() + " 초 지연 되었습니다.<br>");
           
            if (vQuery != null && vQuery.Count() > 0)
            {
                Response.Write("<br>vQuery.Count() 호출 후 : " + sw.Elapsed.Seconds.ToString() + " 초 지연 되었습니다.<br>");
           
                int i = 0;
                foreach (var item in vQuery)
                {
                    if (i != 0 && i % 10000 == 0) //1만번째 마다
                    {
                        Response.Write("<br>vQuery 출력 " + i.ToString("###,###") + " : " + sw.Elapsed.Seconds.ToString() + " 초 지연 되었습니다.<br>");
                    }
                    i++;
                }
            }

 


10만개 select :
string 쿼리는 List<entity>에 결과를 담을 때(.ToList()) 시간이 소요되었고,
var 쿼리는 카운트를 호출할 때(vQuery.Count()) 시간이 소요되었다.
최종결과 : 18초 vs 38초

list 생성 전 : 0 초 지연 되었습니다.

list 생성 후 : 18 초 지연 되었습니다.

list.Count 추출 후 : 18 초 지연 되었습니다.

10,000 : 18 초 지연 되었습니다.

20,000 : 18 초 지연 되었습니다.

:

100,000 : 18 초 지연 되었습니다.

18 초 지연 되었습니다.

DB 접속방식 : linq with string query
Query : SELECT * FROM [dbo].[BIG_DATA_TEST] WHERE NUM <= 100001

 

vQuery 생성 전 : 0 초 지연 되었습니다.

vQuery 생성 후 : 0 초 지연 되었습니다.

vQuery.Count() 호출 후 : 20 초 지연 되었습니다.

vQuery 출력 10,000 : 20 초 지연 되었습니다.

vQuery 출력 20,000 : 21 초 지연 되었습니다.

:

:

vQuery 출력 90,000 : 21 초 지연 되었습니다.

vQuery 출력 100,000 : 38 초 지연 되었습니다.

38 초 지연 되었습니다.

DB 접속방식 : linq with var query
Query : SELECT [Extent1].[NUM] AS [NUM], [Extent1].[TEST_CONTENT] AS [TEST_CONTENT], [Extent1].[FIELD1] AS [FIELD1], [Extent1].[FIELD2] AS [FIELD2], [Extent1].[FIELD3] AS [FIELD3], [Extent1].[FIELD4] AS [FIELD4], [Extent1].[FIELD5] AS [FIELD5], [Extent1].[FIELD6] AS [FIELD6], [Extent1].[FIELD8] AS [FIELD8], [Extent1].[FIELD9] AS [FIELD9], [Extent1].[FIELD10] AS [FIELD10], [Extent1].[GEG_DATE] AS [GEG_DATE] FROM (SELECT [BIG_DATA_TEST].[NUM] AS [NUM], [BIG_DATA_TEST].[TEST_CONTENT] AS [TEST_CONTENT], [BIG_DATA_TEST].[FIELD1] AS [FIELD1], [BIG_DATA_TEST].[FIELD2] AS [FIELD2], [BIG_DATA_TEST].[FIELD3] AS [FIELD3], [BIG_DATA_TEST].[FIELD4] AS [FIELD4], [BIG_DATA_TEST].[FIELD5] AS [FIELD5], [BIG_DATA_TEST].[FIELD6] AS [FIELD6], [BIG_DATA_TEST].[FIELD8] AS [FIELD8], [BIG_DATA_TEST].[FIELD9] AS [FIELD9], [BIG_DATA_TEST].[FIELD10] AS [FIELD10], [BIG_DATA_TEST].[GEG_DATE] AS [GEG_DATE] FROM [dbo].[BIG_DATA_TEST] AS [BIG_DATA_TEST]) AS [Extent1] WHERE [Extent1].[NUM] <= 100001 

 

 

20만개 select :
string 쿼리는 20초, var 쿼리는 41초.. 두 결과 모두 약간씩 시간이 더 소요되었다.
재미난 사실이 발견되었다. var 쿼리의 경우 카운트 호출 후부터 지연이 거의 없다가 마지막 출력되는 단계에서 10만쿼리일때 17초, 20만 쿼리일 때 19초씩 각각 지연되었다.
최종결과 : 20초 vs 41초

 list 생성 전 : 0 초 지연 되었습니다.

list 생성 후 : 20 초 지연 되었습니다.

list.Count 추출 후 : 20 초 지연 되었습니다.

10,000 : 20 초 지연 되었습니다.

 

190,000 : 20 초 지연 되었습니다.

200,000 : 20 초 지연 되었습니다.

20 초 지연 되었습니다.

DB 접속방식 : linq with string query
Query : SELECT * FROM [dbo].[BIG_DATA_TEST] WHERE NUM <= 200001

 

vQuery 생성 전 : 0 초 지연 되었습니다.

vQuery 생성 후 : 0 초 지연 되었습니다.

vQuery.Count() 호출 후 : 19 초 지연 되었습니다.

vQuery 출력 10,000 : 19 초 지연 되었습니다.

:

vQuery 출력 180,000 : 20 초 지연 되었습니다.

vQuery 출력 190,000 : 20 초 지연 되었습니다.

vQuery 출력 200,000 : 41 초 지연 되었습니다.

41 초 지연 되었습니다.

 

 

30만개 select :
이번에도 역시 var 쿼리는 마지막 단계에서 16초 지연되었다. 하지만 신기한 현상이 20만개 일때보다 오히려 30만개 일때 시간이 단축되었다. 일시적인 네트웍 현상일 수도 있다.
최종결과 : 18초 vs 36초

list 생성 전 : 0 초 지연 되었습니다.

list 생성 후 : 18 초 지연 되었습니다.

list.Count 추출 후 : 18 초 지연 되었습니다.

10,000 : 18 초 지연 되었습니다.

 

300,000 : 18 초 지연 되었습니다.

18 초 지연 되었습니다.

DB 접속방식 : linq with string query
Query : SELECT * FROM [dbo].[BIG_DATA_TEST] WHERE NUM <= 300001
 

 

 vQuery 생성 전 : 0 초 지연 되었습니다.

vQuery 생성 후 : 0 초 지연 되었습니다.

vQuery.Count() 호출 후 : 17 초 지연 되었습니다.

vQuery 출력 10,000 : 17 초 지연 되었습니다.

 

vQuery 출력 290,000 : 20 초 지연 되었습니다.

vQuery 출력 300,000 : 36 초 지연 되었습니다.

36 초 지연 되었습니다.

 

 

100만개 select :
string 쿼리는 1/10인 10만개 일때랑 별 차이가 없다.
var 쿼리는 이번에도 역시 마지막 단계에서 15초정도 지연되었다. 마지막에 내부적으로 뭔가를 하는것 같다. 아니 마지막에 메모리에 적재했다가 한꺼번에 뿌려주는 것 같다. 결론은 최종적으로 뿌려준 경과시간이 의미가 있다는것.
최종결과 : 19초 vs 43초

 
list 생성 전 : 0 초 지연 되었습니다.

list 생성 후 : 19 초 지연 되었습니다.

list.Count 추출 후 : 19 초 지연 되었습니다.

10,000 : 19 초 지연 되었습니다.

 

990,000 : 19 초 지연 되었습니다.

1,000,000 : 19 초 지연 되었습니다.

19 초 지연 되었습니다.

DB 접속방식 : linq with string query
Query : SELECT * FROM [dbo].[BIG_DATA_TEST] WHERE NUM <= 1000001

 

 
vQuery 생성 전 : 0 초 지연 되었습니다.

vQuery 생성 후 : 0 초 지연 되었습니다.

vQuery.Count() 호출 후 : 18 초 지연 되었습니다.

vQuery 출력 10,000 : 18 초 지연 되었습니다.

 

vQuery 출력 970,000 : 28 초 지연 되었습니다.

vQuery 출력 980,000 : 28 초 지연 되었습니다.

vQuery 출력 990,000 : 28 초 지연 되었습니다.

vQuery 출력 1,000,000 : 43 초 지연 되었습니다.

43 초 지연 되었습니다.

 

 

200만개 select
string 쿼리는 row 수 대비 큰 차이가 없다.
var 쿼리는 다운 ㅡ,.ㅡ
최종결과 25초 vs 다운

 
list 생성 전 : 0 초 지연 되었습니다.

list 생성 후 : 25 초 지연 되었습니다.

list.Count 추출 후 : 25 초 지연 되었습니다.

10,000 : 25 초 지연 되었습니다.

 :

1,990,000 : 25 초 지연 되었습니다.

2,000,000 : 25 초 지연 되었습니다.

25 초 지연 되었습니다.

DB 접속방식 : linq with string query
Query : SELECT * FROM [dbo].[BIG_DATA_TEST] WHERE NUM <= 2000001

 

 'System.OutOfMemoryException' 형식의 예외가 Throw되었습니다.

 

 

300만개 select :
300만개 에서는 string 쿼리도 다운되었다. 참고로 닷넷의 고전적인 방식인 excuteReader() 로 받아서 list 에 적재해서 뿌려주는 방식은 300만건에 25초, 200만건에 21초에 모두 출력되었다(하단 참고).

 'System.OutOfMemoryException' 형식의 예외가 Throw되었습니다. 

 

[참고] 기본방식 executeReader 로 받아서 list 에 적재 후 출력 (200만건)

SqlDataReader 생성 : 0 초 지연 되었습니다.

list 에 item 적재 : 21 초 지연 되었습니다.

100,000 : 21 초 지연 되었습니다.

200,000 : 21 초 지연 되었습니다.

:

1,900,000 : 21 초 지연 되었습니다.

2,000,000 : 21 초 지연 되었습니다.

21 초 지연 되었습니다. 

Query : SELECT * FROM [dbo].[BIG_DATA_TEST] WHERE NUM <= 2000001

 

종합

 

string 쿼리방식

var 쿼리방식

10만 Row

18초

38초

20만

20초

41초

30만

18초

36초

100만

19초

43초

 200만

 25초

 다운

 300만

 다운

 다운

 

 

개인적인 결론

물론 개인적인 결론이다. 여러가지 경우의 수가 있지만 한가지 방법으로 테스트 했으니 한가지 참고자료로만 생각했으면 좋겠다.

var 쿼리 방식보다는 string 쿼리가 성능상 좋아보이고, 고전적인 executeReader() 방식을 적절히 활용하면 좀 더 좋은 퍼포먼스를 보여주지 않을까 싶다.

 

여기서 끝내면 뭔가 찜찜할 것 같아 vQuery.Count() 를 제외하고 테스트를 해보았다.

10만

vQuery 생성 전 : 0 초 지연 되었습니다.

vQuery 생성 후 : 0 초 지연 되었습니다.

vQuery 출력 10,000 : 0 초 지연 되었습니다.

:

vQuery 출력 90,000 : 1 초 지연 되었습니다.

vQuery 출력 100,000 : 17 초 지연 되었습니다.

17 초 지연 되었습니다.

 

30만

vQuery 생성 전 : 0 초 지연 되었습니다.

vQuery 생성 후 : 0 초 지연 되었습니다.

vQuery 출력 10,000 : 0 초 지연 되었습니다.

:

vQuery 출력 290,000 : 2 초 지연 되었습니다.

vQuery 출력 300,000 : 19 초 지연 되었습니다.

19 초 지연 되었습니다.

 

200만

:

: 

vQuery 출력 980,000 : 9 초 지연 되었습니다.

vQuery 출력 990,000 : 9 초 지연 되었습니다.

vQuery 출력 1,000,000 : 25 초 지연 되었습니다.

25 초 지연 되었습니다.

 

오늘 테스트한 결과를 종합하면 아래와 같다.

var 쿼리로 Count()랑 Row출력을 함께 실행하면 200만에서 다운 됐는데 Row 출력만 실행하면 다운이 되지 않는다. Count() 가져올때도 Row 만큼 비슷한 시간 지연(리소스 사용)이 발생한다는 결과값이다.

 

 string 쿼리(Count+Rows)

 var 쿼리(Count())

var쿼리(Rows) 

 10만 Row

 18초

 20

 17초

 20만

 20

 17

 16

 30만

 18

 19

19

 100만

 15

 18

 26

 200만

 25

다운

25

300만

 다운

 다운

다운 


음.. var 쿼리는 카운트를 가져올 때(.Count())랑 Row 데이타를 뿌려줄때랑 따로 시간이 소요된다. 내가 적절치 못한 테스트를 한건지 이게 맞는것인지 모르겠지만 아무튼 테스트는 그렇게 나왔다.

그럼 linq 쿼리문의 좋은점은 무엇인가? 코드가 간결해지고, 필요한 연산을 한꺼번에 묶을 수 있고, 통합 보안이 더 좋은?? 인터넷에 공개된 linq 쿼리문의 장점들을 보면 장점에 대해 구체적으로 물어보고 싶다. linq 쿼리문이 고전적인 방법보다 성능이 더 좋다는 글도 있던데...??