2016-12-30 7 views
2

많은 테이블이 조인 된 복잡한 쿼리가 있습니다. 복잡성 때문에 실제 쿼리를 작성하기가 어렵습니다.IN 절 안에있는 항목 수가 4 개를 초과하면 SQL Server 쿼리가 매우 느립니다.

때문이다 내가 찾은

select t1.id, t2.id, t1.name, t2.name 
from table1 t1, table2 t2 
left join table3 t3 ON t2.id = t3.id 
where t2.id = t1.ref_id 
    and t1.ref_id IN ('id1', 'id2', 'id3', 'id4', 'id5', ...) 

, 그 내가 IN 절 안에있는 경우 ('ID1', 'ID2', 'ID3'IN이 t1.ref_id 같은 단지 4 개 이하의 값을, '같은 id4 ') 매우 빠르게 작동합니다 (16 밀리 초). tidref_id IN ('id1', 'id2', 'id3', 'id4', 'id5') 실행 시간이 40 배로 늘어나고 600 ms가됩니다. 이 동작을 제어하는 ​​몇 가지 매개 변수가 같은

나는 SQL 서버 것 같습니다 2014 년

에있어. 다른 SQL 서버 (SQL Server 2008)에서이 쿼리를 시도했지만 제한을 찾을 수 없습니다.

내 질문 : 이러한 종류의 동작을 제어하는 ​​매개 변수가 있습니까? 또는이 이상한 한계를 예를 들어 50으로 늘리는 방법.

단지 4 개가 아닌 30-50 개로 늘리고 싶습니다. 물론 수백 수천 개의 값을 가진 IN 절을 생성하고 싶지는 않습니다. 나는 이유를 발견 같은

select t1.id, t2.id, t1.name, t2.name, t3.name 
from table1 t1, table2 t2 
left join table3 t3 ON t2.id = t3.id 
where t2.id = t1.ref_id 
    and t1.ref_id IN ('id1', 'id2', 'id3', 'id4', 'id5', ...) 

이 UPDATE2

가 보이는 :

갱신 1

미안 해요, 난 그렇지 않으면 내가 필요하지 않은 T3처럼 보이는 선택 t3.name을 넣어 잊어 버렸습니다. 문제는 IN 내부의 항목 수에 관한 것이 아닙니다. 나중에이 문제를 4 개 미만의 ID로 재현했습니다 (1 개 포함). 어떤 ID는 t1.ref_id에 표시되지 않았기 때문에 발생합니다. t1.ref_id에 존재하지 않는 id가있을 때, 그것이 빠를 때, t1.ref_id에 존재하는 id를 추가 할 때, 느리게 될 때. 이전 예제에서 id1 - id4는 t1.ref_id에 표시되지 않았고 id5가 제시되었습니다. 이 때문에 id5를 추가 할 때 속도가 느려집니다. IN 절 안에 id (id5)를 1 개만 넣어도 속도가 느려집니다. 마지막으로 t1.ref_id의 인덱스가 문제를 해결했습니다. 4 개 또는 5 개의 ID 주변에는 마법이 없었습니다. 제 구체적인 예에서 우연의 일치입니다.

+0

t1.ref_id에 색인을 생성 했습니까? –

+0

차이를 좁히기 위해 잘 해왔습니다. 이제 느린 버전과 빠른 버전 간의 쿼리 계획을 비교하십시오. 너는 무엇을 보느냐. 쿼리 계획을 보려면 CTRL-L을 누릅니다. –

+2

암시 적 및 명시 적 조인 구문을 함께 사용해서는 안되며 명시 적 구문으로 다시 작성해야합니다. 그것은 1992 년 이래 ANSI 표준입니다! 이 쿼리는 저장 프로 시저의 일부입니까? 'OPTION (RECOMPILE) '을 추가하면 도움이됩니까? – HoneyBadger

답변

1

먼저 쿼리를 수정하십시오. 간단한 규칙 : 쉼표는 FROM 절에 사용하십시오.

select t1.id, t2.id, t1.name, t2.name 
from table1 t1 join 
    table2 t2 
    on t2.id = t1.ref_id left join 
    table3 t3 
    on t2.id = t3.id 
where t1.ref_id in ('id1', 'id2', 'id3', 'id4', 'id5', ...); 

쿼리를 기반으로, 당신은 table3에 대한 필요가 없습니다 - 당신이 중복 행을 걱정하지 않는. 나는 그것을 제거 할 것이다.

그런 다음 색인을 고려해야합니다. 나는 table1(ref_id, id, name)table2(id, name)을 제안 할 것입니다.

또한 ref_id이 실제로 숫자 인 경우 목록의 값을 작은 따옴표로 묶지 마십시오. 문자열과 숫자를 혼합하면 최적화 프로그램을 혼동시킬 수 있습니다.

+0

답변 해 주셔서 감사합니다. 그러나 SQL을 직접 변경할 수없는 제품을 사용하기 때문에 쉼표로 구분 된 테이블에서 JOIN으로 구문을 변경할 수 없습니다. 표 3 데이터를 선택하는 것을 잊었습니다. UPDATE1에서 내 검색어를 변경했습니다. ref_id는 문자열입니다. id는 097777778018f16b와 같은 숫자와 문자가있는 종류의 GUID입니다. 색인 항상 느린 경우 이해할 수 있습니다. 하지만 왜 4 개의 ID는 빠르며 5 개의 ID는 느린가? 비슷하게 생겼지 만 다른 테이블에서 데이터를 가져 오는 다른 쿼리가 있는데 같은 문제가 있습니다. 괜찮 으면 4 값, 5는 느립니다. – Zlelik

+1

이전 조인 구문으로 쿼리를 생성하는 제품? – GuidoG

+0

@GuidoG "DELL EMC Documentum"이라 불리는 Dump 언어 (Documentum Query Language)는 Documentum Content Server에서 자동으로 SQL로 변환됩니다. 이 DQL 쿼리를 작성하고 있습니다. LEFT 조인 구문이 있지만 JOIN 구문이 없습니다. 이 왼쪽 조인 table2 t2 on t2.id = t1.ref_id ...와 같은 LEFT JOIN을 사용하여 JOIN을 시뮬 레이팅하려고 시도했습니다. 여기서 t2.id! = ''이고 작동합니다. 하지만 여전히 IN과 같은 문제가 있습니다. 어쨌든이 쿼리를 조인으로 다시 작성하는 것은 도움이되지 않습니다. 그것은 단지 아름다운 문법을 위해 싸우고 있습니다 :) – Zlelik