2016-12-22 5 views
0

SqlDataAdapter.Fill (DataTable)을 사용하여 테이블에서 간단한 SELECT를 수행하는 프로세스가 포함 된 콘솔 일괄 처리 응용 프로그램이 있습니다.채우기 (DataTable) 테스트에 성공했으며 응답이 없습니다.

private DataTable getMyTable(string conStr) 
    { 
     DataTable tb = new DataTable(); 
     StringBuilder bSql = new StringBuilder(); 
     bSql.AppendLine("SELECT * FROM MyDB.dbo.MyTable"); 
     bSql.AppendLine("WHERE LEN(IdString) > 0");     
     try 
     { 
      string connStr = ConfigurationManager.ConnectionStrings[conStr].ConnectionString; 
      using (SqlConnection conn = new SqlConnection(connStr)) 
      { 
       conn.Open(); 
       using (SqlDataAdapter adpt = new SqlDataAdapter(bSql.ToString(), conn)) 
       { 
        adpt.Fill(tb); 
       } 

      } 
      return tb; 
     }   
     catch (SqlException sx) 
     { 
      throw sx; 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 

이 방법은 동 기적으로 실행되고, 테스트의 많은 개월 동안 여러 테스트 환경에서 성공적으로 실행 된 - 모두 명령 줄에서 시작 또는 AutoSys 작업의 제어하에 시작했을 때.

그러나 프로덕션 환경으로 이동하면 프로세스가 멈추었습니다. Fill 메서드를 사용하면 거의 알 수 있습니다. 더욱이 시간이 초과되는 대신 새로운 요청 스레드가 생성되기 시작했으며 몇 시간 만 지나면 응용 프로그램 서버에서 5GB 이상의 메모리가 소모되었습니다. 이것은 다른 활성 응용 프로그램에 영향을 미치므로 매우 인기가 없었습니다. 예외가 발생하지 않았습니다.

연결 문자열은 마치 평범한 바닐라처럼 보입니다.

"data source=SERVER\INSTANCE;initial catalog=MyDB;integrated security=True;" 

사과는 내가 (이 아래 AutoSys 작업이 실행 된)는 SQL DBA 아래보고 있지만, 우리는 SQL 서버에 넣어 추적을했을 때, 그것은 응용 프로그램 ID를 보였다 무엇에 대한 잘못된 용어를 사용하는 경우 받아 들여지고 유효한 로그인으로. 그런 다음 서버는 SELECT 쿼리를 처리하는 것으로 보입니다. 그러나 결코 응답을 반환하지 않았습니다. 대신, 그것은 "명령 대기 중"상태가되었습니다. 요청 스레드가 몇 분 동안 열린 상태로 유지 된 다음 사라졌습니다.

DBA에 따르면 교착 상태의 징후는 보이지 않지만 차단 여부를 실시간으로 모니터링해야합니다.

프로덕션 환경에서만 발생합니다. 테스트 환경에서 SQL Server는 항상 1 초 이내에 응답했습니다.

AutoSys Application ID는 새로운 것이 아닙니다. 다른 SQL Server와 수년간 사용되어 왔으며 아무런 문제가 없었습니다. DBA는 해당 ID로 로그인 한 프로덕션 SQL 서버에서 SELECT 쿼리를 수동으로 실행하여 정상적으로 응답했습니다.

프로덕션 환경이 아닌 환경에서 문제를 재현 할 수 없으며 서버 관리자가 대기 상태가 아닌 프로덕션 환경에서 프로세스를 종료하기를 주저합니다. 우리의 보안 요구 사항은 서버 로그 및 프로세스를 볼 수있는 나의 액세스를 제한하며, 보통 나를 위해 다른 전문가를 고용해야합니다.

조만간이 문제를 해결해야합니다. 현재보고있는 데이터의 양은 단지 몇 줄에 불과하지만 향후 몇 개월 동안 증가 할 것입니다. 무슨 일이 일어나고 있는지, 응용 프로그램 서버와 SQL 서버 사이의 통신 및/또는 보안이 관련되어 있다는 것이 가장 좋습니다.

추가 아이디어 나 조사 할 항목을 환영합니다. 모두에게 감사드립니다.

+0

대용량 데이터베이스의 경우 VS에서 쿼리를 완료하는 데 오랜 시간이 걸릴 수 있습니다. 걸기 방지 BackGroundWorker를 사용하여 작업을 수행합니다. SQL Server와 함께 제공되는 명령 줄 실행 파일 인 cmd.exe를 사용하여 쿼리를 수행하고 결과가 포함 된 csv 파일을 생성합니다. 그런 다음 VS 응용 프로그램으로 결과를 읽습니다. cmd.exe를 C#에서 backgbroundworker 내부의 프로세스 클래스를 사용하여 실행합니다. – jdweng

+0

@ jdweng : 나는 그것이 좋은 지적이라고 생각한다. 그것은 하나의 간단한 선택 진술은 SQL 명령 줄 도구에서 가능성을 제외, 그 응용 프로그램 내부에 뭔가 잘못 실행하는 경우. 테이블이 얼마나 큽니까? TOP 1000으로 선택을 실행하여 결과 데이터가 예상대로 작동하는지 확인할 수 있습니다. 처음에는 csv에 데이터를 쓰는 것이 이상하게 들리지만 실제로는 큰 데이터를 사용하는 것이 좋습니다. –

+0

내 응용 프로그램에서 sqlcmd.exe는 10GB 데이터베이스에서 30 분 이상을 사용하고있었습니다. C#에서 쿼리로 시간이 걸렸습니다. 그리고 쿼리가 실행되는 동안 응용 프로그램에 대한 내 윈도우가 멈췄다. sqlcmd.exe의 결과를 C#으로 가져 오는 유일한 방법은 csv 파일을 사용하는 것입니다. – jdweng

답변

0

일부 이상한 사용 권한/ADO가 원인 일 수 있지만그것을 또는 적어도를 하드 중 - 쿼리를 DBA가 수동으로 실행하고 응용 프로그램에서 실행되는 동일한 지 확인

  1. : @user1895086에서 언급 한 바와 같이 NET 문제는, 나는 그럼에도 불구하고 몇 가지를 한 번 더 다시 확인하는 것이 좋습니다 것 실행하기 바로 전에 기록하십시오. 미안보다 안전 해하는 것이 낫습니다.
  2. 몇 줄만 선택하십시오.이를 피할 수 있으면 전체 표를 선택하지 않는 것이 좋습니다. 우리의 경우 SELECT TOP 1 (또는 100) 질의는 이러한 문제를 나타내지 않을 수 있습니다. 아마 당신이 생각하는 것보다 훨씬 더 많은 데이터가 있고 ADO.Net은 모든 행을로드하려고합니다. 아니면 그렇지 않을 수도 있습니다.
  3. SqlDataAdapter가 문제를 일으키지 않도록하려면 SqlDataReader을 시도하십시오. 예, 동일한 DataAdapter internally을 사용하지만 최소한 추가 작업을 용의자 목록에서 제외합니다.
  4. 5GB의 메모리 - analyzing memory dumps으로 덤프에 손을 넣으려고 시도하는 것은 쉬운 일이 아니지만 그 엄청난 양의 메모리를 먹는 것을 이해하는 것은 그리 어렵지 않을 것입니다. 왜냐하면 나는 ADO.NET이 아무 이유없이 많은 추가 객체를 생성 할 것이라는 것을 어떻게 든 의심하기 때문입니다.
+0

SQL Server에서 수신 한 것과 비교하여 응용 프로그램이 보낸 쿼리를 비교하라는 제안 때문에이 대답을 받아 들였습니다. 위의 메소드를 실행 한 다음 Entity Framework를 사용하여 다른 DB에 액세스하는 메소드에서 실제로 발생했습니다. LINQ 표현식은 EF가 기껏해야 몇백 개의 행을 선택하도록되어있었습니다. 대신 LINQ에서 변환 한 쿼리는 전체 170 만 개의 행 테이블을 메모리에로드하고 3 개의 개별 요청 스레드에서로드하려고했습니다. – 66AndStillLearning

1

이것은 사용 권한과 관련이있을 수 있습니다. SQL Server는 때로는 적절한 오류 메시지를주는 대신 이상한 일을합니다.

내 제안, 그리고 어쨌든 성능을 향상시킬 수있는 선택을 실행하는 서버 쪽 저장 프로 시저를 작성하고 저장 프로 시저를 호출하는 것입니다. 이렇게하면 DBA는 테이블에 직접 액세스하지 않고도 스토어드 프로 시저에 대한 적절한 액세스를 보장 할 수 있습니다. 이유는 무엇인가가 차단되어 있고 약간의 성능 향상이 있어야합니다.

+1

여기 거의 모든 내용에 동의하지만 왜 저장 프로 시저가 임시 쿼리보다 성능이 향상 될 것이라고 생각합니까? –

+0

프로그래머 사이에 분열을 일으키며 한동안 논쟁이 벌어지고 있습니다. 특히 윈도우가 좁아졌습니다. 훨씬 더 큰 차이를 만든 시간이 있었지만 지금은 환경에 기반을두고 있습니다. 여전히 스토어드 프로 시저를 사용하면 성능이 약간 향상됩니다 (DBMS에 쿼리를 최적화 할 수있는 자유가 더 많은 것처럼 보입니다.) 이유는 무엇입니까? 저는 DBA가 아닙니다. 임시로 사용할 때 발생할 수있는 함정을 방지하고 또한 코드를 다시 컴파일하고 소비자에게 다시 배포 할 필요없이 쿼리 매개 변수를 변경할 수 있습니다. – CDove

+0

성능을 향상시키지 않습니다. 실행은 SQL 6.5 (거의 20 년 전) 이후의 저장 프로 시저와 동일한 임시 쿼리를 위해 컴파일되고 캐시됩니다. 나는 스토어드 프로 시저에 대한 임시 질의를 선호한다는 말은 아니다. 반대로 나는 저장된 procs에 찬성하여 모든 방금 언급 한 이유에 대한 내 자신의 특별 쿼리를 작성하지 않을 것입니다. 그러나 저장 프로 시저가 임시 쿼리보다 빠르다는 것이 장기 실행 오류입니다. 단순히 사실이 아닙니다. 저장된 procs에 대한이 기사를 확인하십시오. https://sqlperformance.com/2013/05/t-sql-queries/another-argument-for-stored-procedures. –

관련 문제