SQL Server 2005의 대규모 크로스 조인
-
21-08-2019 - |
문제
나는 거대한 과정을 만들고 있습니다 CROSS JOIN
두 테이블의. 결과 테이블에는 15m 레코드가 포함되어 있습니다 (프로세스는 2600 행 테이블과 12000 행 테이블과 30m 크로스 조인을 한 다음 일부 그룹을 수행하여 반으로 분할해야합니다). 행은 상대적으로 좁습니다 - 단 6 개의 열만. 완료 조짐없이 5 시간 동안 운영되었습니다. 나는 단지 알려진 상품과 크로스 조인에 대해 기대할 수있는 것 사이의 불일치가 있음을 알았으므로 내 출력은 최종 테이블을 절반으로 줄이는 그룹화 또는 전용이 없습니다. 그러나 여전히 완료하지 않을 것 같습니다. 곧 시간.
먼저 가능한 경우 프로세스 에서이 테이블을 제거하려고합니다. 분명히 두 테이블에 개별적으로 결합하여 대체 될 수 있지만 지금은 다른 곳에 대한 가시성이 없습니다.
그러나 기존 프로세스가 수행한다는 점을 감안할 때 (초점 언어를 사용하여 덜 강력한 기계에서) 대형 성능을 향상시키는 옵션이 있습니까? CROSS JOIN
SQL Server (2005)의 S (하드웨어는 실제로 옵션이 아닙니다.이 상자는 32GB의 RAM이있는 64 비트 8 방향)?
세부:
이 방법으로 초점을 맞추고 있습니다 (SQL의 크로스 조인 인 동일한 출력을 생성하려고합니다) :
JOIN CLEAR *
DEFINE FILE COSTCENT
WBLANK/A1 = ' ';
END
TABLE FILE COSTCENT
BY WBLANK BY CC_COSTCENT
ON TABLE HOLD AS TEMPCC FORMAT FOCUS
END
DEFINE FILE JOINGLAC
WBLANK/A1 = ' ';
END
TABLE FILE JOINGLAC
BY WBLANK BY ACCOUNT_NO BY LI_LNTM
ON TABLE HOLD AS TEMPAC FORMAT FOCUS INDEX WBLANK
JOIN CLEAR *
JOIN WBLANK IN TEMPCC TO ALL WBLANK IN TEMPAC
DEFINE FILE TEMPCC
CA_JCCAC/A16=EDIT(CC_COSTCENT)|EDIT(ACCOUNT_NO);
END
TABLE FILE TEMPCC
BY CA_JCCAC BY CC_COSTCENT AS COST CENTER BY ACCOUNT_NO
BY LI_LNTM
ON TABLE HOLD AS TEMPCCAC
END
따라서 필요한 출력은 실제로 크로스 조인입니다 (각 측면에서 빈 열이 결합됩니다).
SQL에서 :
CREATE TABLE [COSTCENT](
[COST_CTR_NUM] [int] NOT NULL,
[CC_CNM] [varchar](40) NULL,
[CC_DEPT] [varchar](7) NULL,
[CC_ALSRC] [varchar](6) NULL,
[CC_HIER_CODE] [varchar](20) NULL,
CONSTRAINT [PK_LOOKUP_GL_COST_CTR] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY
= OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [JOINGLAC](
[ACCOUNT_NO] [int] NULL,
[LI_LNTM] [int] NULL,
[PR_PRODUCT] [varchar](5) NULL,
[PR_GROUP] [varchar](1) NULL,
[AC_NAME_LONG] [varchar](40) NULL,
[LI_NM_LONG] [varchar](30) NULL,
[LI_INC] [int] NULL,
[LI_MULT] [int] NULL,
[LI_ANLZ] [int] NULL,
[LI_TYPE] [varchar](2) NULL,
[PR_SORT] [varchar](2) NULL,
[PR_NM] [varchar](26) NULL,
[PZ_SORT] [varchar](2) NULL,
[PZNAME] [varchar](26) NULL,
[WANLZ] [varchar](3) NULL,
[OPMLNTM] [int] NULL,
[PS_GROUP] [varchar](5) NULL,
[PS_SORT] [varchar](2) NULL,
[PS_NAME] [varchar](26) NULL,
[PT_GROUP] [varchar](5) NULL,
[PT_SORT] [varchar](2) NULL,
[PT_NAME] [varchar](26) NULL
) ON [PRIMARY]
CREATE TABLE [JOINCCAC](
[CA_JCCAC] [varchar](16) NOT NULL,
[CA_COSTCENT] [int] NOT NULL,
[CA_GLACCOUNT] [int] NOT NULL,
[CA_LNTM] [int] NOT NULL,
[CA_UNIT] [varchar](6) NOT NULL,
CONSTRAINT [PK_JOINCCAC_KNOWN_GOOD] PRIMARY KEY CLUSTERED
(
[CA_JCCAC] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY
= OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
SQL 코드로 :
INSERT INTO [JOINCCAC]
(
[CA_JCCAC]
,[CA_COSTCENT]
,[CA_GLACCOUNT]
,[CA_LNTM]
,[CA_UNIT]
)
SELECT Util.PADLEFT(CONVERT(varchar, CC.COST_CTR_NUM), '0',
7)
+ Util.PADLEFT(CONVERT(varchar, GL.ACCOUNT_NO), '0',
9) AS CC_JCCAC
,CC.COST_CTR_NUM AS CA_COSTCENT
,GL.ACCOUNT_NO % 900000000 AS CA_GLACCOUNT
,GL.LI_LNTM AS CA_LNTM
,udf_BUPDEF(GL.ACCOUNT_NO, CC.COST_CTR_NUM, GL.LI_LNTM, 'N') AS CA_UNIT
FROM JOINGLAC AS GL
CROSS JOIN COSTCENT AS CC
이 테이블이 어떻게 사용되는지에 따라, 제작에 사용되는 원래 테이블에만 연결하여 프로세스에서 제거 할 수 있어야합니다. 그러나 이것은 매우 큰 포팅 노력이며, 한동안 테이블 사용을 찾지 못할 수도 있으므로 트릭이 있는지 궁금했습니다. CROSS JOIN
적시에 큰 테이블을 적시에 넣습니다 (특히 초점의 기존 프로세스가 더 신속하게 수행 할 수 있다는 점을 감안할 때). 그렇게하면 교체 쿼리 건물의 정확성을 검증 한 다음 나중에보기 등으로 고려할 수 있습니다.
또한 UDFS와 문자열 조작을 고려하고 크로스 조인을 먼저 수행하여 프로세스를 조금 깨뜨리는 것을 고려하고 있습니다.
지금까지 결과 :
UDF는 성능에 많은 기여를한다는 것이 밝혀졌습니다. 그러나 15m 행 크로스 조인과 30m 행 크로스 조인 사이에는 큰 차이가있는 것으로 보입니다. 나는 쇼 계획 권리 (boo hoo)가 없으므로 인덱스를 변경 한 후 사용중인 계획이 더 나은지 더 나쁘게 알 수 없습니다. 아직 리팩토링되지 않았지만 전체 테이블이 곧 사라질 것으로 기대합니다.
해결책
이 쿼리를 검사하면 한 테이블에서 사용 된 열 하나만 사용하고 다른 테이블에서 사용 된 두 개의 열만 표시됩니다. 사용 된 열의 수가 매우 적기 때문에이 쿼리는 커버링 인덱스로 쉽게 향상 될 수 있습니다.
CREATE INDEX COSTCENTCoverCross ON COSTCENT(COST_CTR_NUM)
CREATE INDEX JOINGLACCoverCross ON JOINGLAC(ACCOUNT_NO, LI_LNTM)
추가 최적화를위한 내 질문은 다음과 같습니다.
쿼리를 쿼리 분석기에 넣고 "예상 실행 계획"버튼을 whack하면 무엇을 할 것인지에 대한 그래픽 표현이 표시됩니다.
가입 유형 : 중첩 루프 조인이 있어야합니다. (다른 옵션은 병합 조인 및 해시 조인입니다). 중첩 루프가 보이면 괜찮습니다. Merge Join 또는 Hash Join이 표시되면 알려주십시오.
테이블 액세스 순서 : 맨 위로 이동하여 오른쪽으로 끝까지 스크롤하십시오. 첫 번째 단계는 테이블에 액세스해야합니다. 어떤 테이블이 사용되는 방법과 어떤 방법이 사용됩니다 (색인 스캔, 클러스터 된 인덱스 스캔)? 다른 테이블에 액세스하는 데 어떤 방법이 사용됩니까?
병렬성 : 계획의 거의 모든 아이콘에 작은 Jaggedy 화살이 병렬 처리가 사용되고 있음을 나타내는 것을 볼 수 있습니다. 이것을 보지 못하면 큰 문제가 있습니다!
UDF_BUPDEF가 저와 관련이 있습니다. 추가 테이블에서 읽습니까? util.padleft는 저를 덜 걱정하지만 여전히 .. 무엇입니까? 데이터베이스 개체가 아닌 경우 대신 사용하는 것을 고려하십시오.
RIGHT('z00000000000000000000000000' + columnName, 7)
Joinccac에 트리거가 있습니까? 인덱스는 어떻습니까? 이 큰 삽입을 사용하면 해당 테이블에 모든 트리거와 인덱스를 떨어 뜨릴 수 있습니다.
다른 팁
다른 사람들의 말을 계속하면서 DB는 선택에 사용되는 쿼리를 포함하는 기능을 통해 항상 내 쿼리를 매우 느리게 만들었습니다. 머리 꼭대기에서 45 초 안에 쿼리를 실행 한 다음 기능을 제거한 다음 결과 0 초입니다. :)
따라서 UDF_BUPDEF가 쿼리를 수행하지 않는지 확인하십시오.
쿼리를 분해하여 간단한 크로스 조인으로 만듭니다.
SELECT CC.COST_CTR_NUM, GL.ACCOUNT_NO
,CC.COST_CTR_NUM AS CA_COSTCENT
,GL.ACCOUNT_NO AS CA_GLACCOUNT
,GL.LI_LNTM AS CA_LNTM
-- I don't know what is BUPDEF doing? but remove it from the query for time being
-- ,udf_BUPDEF(GL.ACCOUNT_NO, CC.COST_CTR_NUM, GL.LI_LNTM, 'N') AS CA_UNIT
FROM JOINGLAC AS GL
CROSS JOIN COSTCENT AS CC
단순한 크로스 가입이 얼마나 좋은지 보십니까? (기능이 적용되지 않으면)