2009-09-25 7 views
0

큰 느린 dataloading 쿼리의 성능을 향상 (죄송합니다 전에이 글을 쓰는하지 않는)내가 Oracle에서 SQL Server로 데이터를로드하기 위해 노력하고있어

나는 (실제로는 다른 테이블의 데이터가있는보기) 테이블이 있습니다 1 백만 레코드 이상. 내가 비즈니스 로직을위한 함수를 가지고 있고 select 쿼리에서 직접 호출하는 방식으로 패키지를 디자인했습니다.

예 :

X1(id varchar2) 
x2(id varchar2, d1 date) 
x3(id varchar2, d2 date) 

Select id, x, y, z, decode (.....), x1(id), x2(id), x3(id) 
FROM Table1 

참고 : 내 테이블 (20) 열이 나는이어야 6-7 열에서 5 개 개의 다른 함수를 호출. 그리고 일부 기능은 감사 테이블에 전달 된 매개 변수를 비교하고 논리를 수행 난 내 쿼리의 성능을 향상 시키거나 거기에 내가 C# 코드 만의 초기 선택에서 그 일을 시도이

을 할 수있는 더 좋은 방법입니다 수있는 방법

레코드가 데이터 집합에 충분할만큼 커야하고 예외적 인 예외가 발생합니다.

내 기능 선택을 수행 한 후, 예를 들어 논리를 수행

Function(c_x2, eid) 

    Select col1 
    into p_x1 
    from tableP 
    where eid = eid; 

    IF (p_x1 = NULL) THEN 
    ret_var := 'INITIAL'; 
    ELSIF (p_x1 = 'L') AND (c_x2 = 'A') THEN 
    ret_var:= 'RL'; 

    INSERT INTO Audit 
     (old_val, new_val, audit_event, id, pname) 
    VALUES 
     (p_x1, c_x2, 'RL', eid, 'PackageProcName'); 

    ELSIF (p_x1 = 'A') AND (c_x2 = 'L') THEN 
    ret_var := 'GL'; 

    INSERT INTO Audit 
     (old_val, new_val, audit_event, id, pname) 
    VALUES 
     (p_x1, c_x2, 'GL', eid, 'PackgProcName'); 

    END IF; 

RETURN ret_var; 
+0

1,000,000 개의 모든 레코드에 대해 이러한 함수를 실행 하시겠습니까? 네, 실행하는 데 약간의 시간이 걸릴 것입니다. 확실히 밀리 초가 아닙니다. 당신의 기대는 무엇입니까? – Guy

+0

나는 밀리 세컨드를 원한다고 말한 적이 없으며, 1 시간 동안 실행 중이다. 그래서 성능을 향상시키고 싶다. (말하자면 ...) 나는 눈 깜짝 할 순간에 끝내기를 원한다. 쓸데없는 것 같아. –

+1

내 것을 보아라. 최신 답변 편집 –

답변

0

먼저 성능 문제가 실제로 어디에 있는지 찾아야합니다. 그런 다음 그것을 해결하려고 할 수 있습니다.

  1. 보기의 성능은 어떻습니까? 함수 호출없이 을 실행하려면 시간이 얼마나 걸립니까? 명령을 실행 해보십시오.

    성능은 얼마나 좋습니까?1 분 또는 1 시간이 걸립니까?

     
    create table the_view_table 
    as 
    select * 
    from the_view; 
    
  2. 기능은 얼마나 잘 수행됩니까? 설명에 따르면 약 500 만 건의 함수 호출을 수행합니다. 그들은 훨씬 더 효율적이었습니다! 또한 함수는 deterministic으로 정의됩니다. 함수가 deterministic 키워드를 사용하여 정의 된 경우 Oracle은 일부 호출을 최적화 할 수 있습니다.

  3. 함수 호출 횟수를 줄이는 방법이 있습니까? 뷰가 평가되고 백만 행의 데이터를 사용할 수있게되면 함수가 호출됩니다. 하지만 가장 높은 수준의 쿼리 입력 값입니까? 함수 호출을 낮은 수준의 뷰에 임베드 할 수 있습니까? 다음 두 가지 쿼리를 고려하십시오. 어느 것이 더 빠를까요? 이 기능을 더 적은 시간을 전화로

    select 
        f.dim_id, 
        d.dim_col_1, 
        long_slow_function(d.dim_col_2) as dim_col_2 
    from large_fact_table f 
    join small_dim_table d on (f.dim_id = d.dim_id)
    select 
        f.dim_id, 
        d.dim_col_1, 
        d.dim_col_2 
    from large_fact_table f 
    join (
        select 
        dim_id, 
        dim_col_1, 
        long_slow_function(d.dim_col_2) as dim_col_2 
    from small_dim_table) d on (f.dim_id = d.dim_id)

    이상적으로 두 번째 쿼리가 더 빨리 실행해야합니다.

성능 문제는 이러한 장소의있을 수 있고 당신이 문제를 조사 할 때까지, 어디 조정 노력을 지시하는 방법을 알고 어렵다.

+0

고마워요, 다시 함수 및 쿼리를 통해 갈 것이고, 어떻게 불필요한 호출을 피할 수 있는지 보게 될 것입니다. –

0

은 테이블에 정렬 된 인텍스를 생성합니다.

Introduction to SQL Server Indizes, 다른 RDBMS는 유사합니다. 당신은 귀하의 질문에 편집 된 이후

편집 : 그것에서 하나의 행을 쿼리 특히 뷰를 사용

는 더 하위에 최적입니다. 나는 당신의 "비즈니스 기능"이 실제로 저장 프로 시저와 같은 것이라고 생각합니까?

다른 사람들이 제안했듯이 SQL에서는 항상 기본 설정을 사용합니다. 나는 이미 그렇게했다고 가정 했으므로 색인 생성을 사용하기 시작했습니다.

0

팁 몇 :

  • 가 RAM에 모든 레코드를로드하지만 하나씩 처리하지 마십시오.
  • 가능한 한 많은 기능을 클라이언트에서 실행하십시오. 데이터베이스는 사용자 정의 함수를 실행하는 데 너무 느립니다.
  • 두 테이블을 조인해야하는 경우 클라이언트에서 두 개의 연결을 만들 수 있습니다. 연결 1로 데이터 주 데이터를 가져오고 연결 2로 감사 데이터를 가져옵니다. 두 연결의 데이터를 모두 같은 순서로 정렬하여 두 연결에서 단일 레코드를 읽고 필요한 모든 작업을 수행 할 수 있습니다.
  • 함수가 항상 동일한 입력에 대해 동일한 결과를 반환하는 경우 계산 열 또는 구체화 된보기를 사용하십시오. 데이터베이스는 함수를 한 번 실행하여 어딘가에 테이블에 저장합니다. 그러면 INSERT은 느리지 만 SELECT은 빠릅니다.
+0

나는 C#에서 각 행을 가져오고 C#에서 논리를 수행하고 다음을 삽입하는 데이터 렌더링을 사용하여 동일한 코드를 작성했습니다 ... 이것은 많은 시간을 소모합니다 ... 함수는 매개 변수를 취하여 수행합니다 몇 가지 논리 : 비교 및 ​​다음 날짜 또는 다른 데이터 계산 ... 내 쿼리에서 조인을 사용하지 않습니다. –

+3

(-1) 레코드 기반 레코드 사용 안 함. 빠른 원시 SQL 함수를 사용해보십시오. DB를 DB로 사용 - 조인/업데이트/쿼리 용으로 제작되었습니다. 우리가 프로그래밍 기술에서 데이터베이스를 재구성 할 수 있다고 생각하지 마십시오. – Guy

+0

나는 SQL에서 C#에서 함수를하고 있어요. 내 기억에 항상 한 번에 모든 것을로드하려고하면 데이터 예외를 사용하는 메모리 예외가 발생합니다 ... DB가 무엇인지에 대해 알고 있습니다 ... 나는 대답을 얻으려고 노력하고있어 DB PLZ를 다시 쓰지 않는 것을 배울 것입니다 ... –

4

나는 각 행을 받고 C#으로 로직을 수행하고 SELECT에서 가능 INSERT이 경우

를 삽입 해요 :

INSERT INTO YourNewTable 
     (col1, col2, col3) 
    SELECT 
     col1, col2, col3 
     FROM YourOldTable 
     WHERE .... 

이 빨리 크게을 를 실행합니다 결과 집합을 반복하고 각 행에 대한 INSERT가있는 단일 쿼리보다. 영업 질문 편집에 대한 같은

편집 :

당신은 당신의 쿼리에서 일반 SQL의 함수 호출을 대체 할 수 있어야한다. LEFT JOIN tableP를 사용하여 "initial"을 모방하고 CASE를 사용하여 "RL"또는 "GL"을 계산할 수 있습니다. OP 최근 의견에 따라

편집는 :에 이동 한 도움을 줄 수 다시이 질문을 읽지 않습니다 대부분의 사람들 :

당신이 SQL 서버에 오라클에서 데이터를로드하기 때문에, 이것은 내가 할 것 인 것이다 , 당신이 말하는 새로운 질문을 엽니 다. 1) Oracle (버전)에서 SQL Server 버전 2로 데이터를로드해야합니다. 현재 C#의 각 행을 처리하는 하나의 쿼리에서로드하고 SQL Server에 삽입합니다. 천천히. 그리고 다른 모든 세부 사항. 데이터를 SQL Server로 대량로드하는 훨씬 좋은 방법이 있습니다. 이 질문에 관해서는, 당신은 대답을 수락 할 수 있습니다, 당신은 당신이 새로운 질문을하거나, 그냥 받아 들일 필요가 없다고 설명 할 필요가 있다고 설명합니다.

+0

SQL 서버에 oracle 테이블을로드하고 있기 때문에 select into insert가 작동하지 않습니다 그리고 CASE를 사용하면 삽입 감사를 수행 할 수 없습니다 –

+1

와우! SQL Server_에 오라클 테이블을로드하지 않았을 것입니다. 질문에 넣은 것이 있습니까? 오른쪽 상단에 ?? –

2

제 추천은 이 아니며은 함수를 사용하고 다른 SELECT 문 내에서 호출하는 것이 좋습니다.

SELECT t.id, ... 
     (SELECT x.column FROM x1 x WHERE x.id = t.id) 
    FROM TABLE t 

캡슐화 등등/C#을 사용하는 경우와 같이 SQL에서 작동하지 않습니다 :이 :에

SELECT t.id, ... 
     x1(t.id) ... 
    FROM TABLE t 

... 동일합니다. 접근 방식을 사용하면 유지 관리가 쉬워 지지만 하위 선택 항목은 반환되는 모든 행에 대해 실행되므로 성능이 저하됩니다. 그래서 당신이 그것을 사용할 수 있습니다 ...

SELECT x.id 
     x.column 
    FROM x1 x 

다음 SELECT의 :

더 나은 방법 ("where x.id = t.id"진짜 하나의 부족 IE) 조인 기준을 포함하도록 지원하는 기능을 업데이트하는 것입니다 같은 가입 :

SELECT t.id, ... 
     x1.column 
    FROM TABLE t 
    JOIN (SELECT x.id, 
       x.column 
      FROM MY_PACKAGE.x) x1 ON x1.id = t.id 

내가 선호하는 유지 보수의 위해 쿼리에 함수 로직을 통합 할 필요가 있지만, 때로는 도움이 될 수 없습니다합니다.

+0

+1, 직장에서 여러 가지 문제가 있습니다. 저는 이것을 생각했지만 SELECT의 INSERT를 사용했습니다. 당신은 내가 가진 것보다 더 나은 기능 문제를 설명했다 ... –

+0

누군가 나를 위해 위의 코멘트를 편집 할 수 있습니다. 나는 코드 스 니펫을 추가하고 싶습니다. –

+0

질문을 편집하고 코드를 넣으십시오. __BOLD__ 및 _ITALICS_는 코드 형식이 아닙니다. –

1

개인적으로이 작업을 수행하기 위해 SSIS 가져 오기를 만듭니다. 사용량이 많으면 삽입 속도가 빨라지고 SSIS는 대량 삽입 후에 기능 부분을 처리 할 수 ​​있습니다.

관련 문제