이 글은 기계 번역의 미러 문서이며, 원본 기사로 바로 이동하려면 여기를 클릭해 주세요.

보기: 10757|회답: 0

[출처] SQL 쿼리 속도를 개선하기 위한 30가지 포인트

[링크 복사]
게시됨 2015. 1. 27. 오후 8:09:54 | | |

1. 쿼리를 최적화하려면 전체 테이블 스캔을 피하고, 먼저 관련된 열에 인덱스를 생성하고 순서를 정하는 것을 고려해야 합니다.



2. where절의 필드에 대해 널 값 판단을 피하려고 노력하세요. 그렇지 않으면 엔진이 인덱스 사용을 포기하고 다음과 같은 전체 테이블 스캔을 수행하게 됩니다:

num이 null인 경우 t에서 ID 선택(select id for t)

num의 기본값을 0으로 설정하고, 테이블의 num 열에 null 값이 없는지 확인한 다음, 이렇게 쿼리할 수 있습니다:

숫자=0인 T에서 ID 선택(Select Select)



3. where절에서 != 또는 <> 연산자를 사용하지 않도록 주의하세요. 그렇지 않으면 엔진이 인덱스 사용을 포기하고 전체 테이블 스캔을 수행하게 됩니다.



4. 조건을 결합하기 위해 where절에서 OR을 사용하지 않도록 주의해야 합니다. 그렇지 않으면 엔진이 인덱스 사용을 포기하고 다음과 같은 전체 테이블 스캔을 수행하게 됩니다:

숫자=10 또는 숫자=20인 T에서 ID를 선택하세요.

이렇게 쿼리할 수 있습니다:

숫자=10인 T에서 ID를 선택하세요

유니언 올

숫자=20인 T에서 ID 선택을



5.in 및 'not in'도 주의해서 사용해야 하며, 그렇지 않으면 다음과 같은 전체 테이블 스캔으로 이어질 수 있습니다:

n in(1,2,3)인 T 중에서 ID 선택.

연속 값의 경우, 만약 'in between interween'을 사용할 수 있다면 사용하지 마세요:

숫자가 1과 3 사이에 있는 T에서 ID를 선택하세요.



6. 다음 쿼리는 전체 테이블 스캔을 유도합니다:

이름이 '%abc%'처럼 된 T에서 ID를 선택하세요.

효율성을 높이기 위해 전체 텍스트 검색을 고려해 보세요.



7. where절에 매개변수를 사용하면 전체 테이블 스캔이 발생합니다. SQL은 런타임에만 로컬 변수를 해결하지만, 옵티마이저는 런타임에 접근 계획 선택을 미룰 수 없기 때문입니다; 컴파일 시점에 반드시 선택되어야 합니다. 하지만 컴파일 시점에 접근 계획이 설정되면 변수의 값을 아직 알 수 없으므로 인덱스 선택의 입력 항목으로 사용할 수 없습니다. 다음 성명서들은 전면을 스캔할 예정입니다:

숫자=@num 중에서 T에서 ID를 선택합니다

쿼리에 인덱스를 강제로 사용할 수 있습니다:

T에서 ID를 선택하며(index(index(index(index name)) 여기서 num=@num



8. where절에서 필드를 표현하는 것을 피하려 노력하세요. 이 경우 엔진이 인덱스 사용을 포기하고 전체 테이블 스캔을 선호하게 됩니다. 예를 들어:

숫자/2=100인 T에서 ID를 선택하세요

다음과 같이 변경해야 합니다:

숫자=100*2인 T에서 ID를 선택하세요



9. where절의 필드에 함수 연산을 수행하지 않도록 주의하세요. 이로 인해 엔진이 인덱스 사용을 포기하고 전체 테이블 스캔을 선호하게 됩니다. 예를 들어:

여기서 T에서 ID(name,1,3)='abc' -name id 중 abc로 시작하는 경우

Datediff(day, createdate, '2005-11-30')=0--'2005-11-30' 생성 ID

다음과 같이 변경해야 합니다:

이름이 'ABC%'처럼 된 T에서 ID를 선택하세요

여기서 T에서 ID를 선택하세요. 여기서 createdate>='2005-11-30' 및 createdate<'2005-12-1'



10. 여기서 절의 "=" 왼쪽에 있는 함수, 산술 연산 또는 기타 표현식 연산을 수행하지 마세요. 그렇지 않으면 시스템이 인덱스를 올바르게 사용할 수 없을 수 있습니다.



11. 인덱스 필드를 조건으로 사용할 때, 인덱스가 복합 인덱스라면, 인덱스의 첫 번째 필드를 조건으로 사용해야 하며, 그렇지 않으면 인덱스가 사용되지 않고, 필드 순서가 가능한 한 인덱스 순서와 일치해야 합니다.



12. 빈 테이블 구조를 생성하는 것과 같은 의미 없는 쿼리를 작성하지 마세요:

1=0 때 t에서 col1,col2를 #t로 선택한다

이 유형의 코드는 결과 집합을 반환하지 않지만 시스템 자원을 소모하므로 다음과 같이 변경해야 합니다:

테이블 생성 #t(...)



13. 많은 경우 를 exists로 대체하는 것이 좋은 선택입니다:

A에서 num을 선택하고, 여기서 num이 들어갑니다(b에서 num을 선택합니다)

다음 문장으로 대체합니다:



여기서 A에서 NUM을 선택한다(num=a.num 여기서 B에서 1을 선택).

14. 모든 인덱스가 쿼리에 유효한 것은 아니며, SQL은 쿼리를 최적화하기 위해 테이블 내 데이터를 기반으로 합니다. 인덱스 열에 많은 데이터 중복이 있을 경우, 테이블에 성별, 남성, 여성 필드가 있는 경우, 인덱스가 거의 절반에 달하는 경우, 인덱스가 성별에 기반하더라도 쿼리 효율성에 영향을 미치지 않습니다.



15. 인덱스가 많을수록 더 좋지 않다. 인덱스는 해당 선택의 효율성을 확실히 향상시킬 수 있지만, 인서트나 업데이트할 때 인덱스가 재구성될 수 있기 때문에 인서트 및 업데이트의 효율을 떨어뜨리므로, 특정 상황에 따라 인덱스를 어떻게 구축할지 신중하게 고려해야 한다. 테이블에 인덱스가 6개를 넘지 않는 것이 좋으며, 너무 많으면 드문 열에 인덱스를 만들어야 하는지 고려하세요.



16. 클러스터 인덱스 데이터 열의 업데이트는 가능한 한 피해야 합니다. 클러스터 인덱스 데이터 열의 순서는 테이블 레코드의 물리적 저장 순서이며, 열값이 변경되면 전체 테이블 레코드의 순서가 조정되어 상당한 자원을 소모하게 됩니다. 애플리케이션이 클러스터 인덱스 열을 자주 업데이트해야 한다면, 인덱스를 클러스터 인덱스로 만들어야 하는지 고려해야 합니다.



17. 숫자 필드를 사용하려고 노력하고, 숫자 정보만 문자로 포함하는 필드를 설계하지 마세요. 이는 쿼리와 연결 성능을 저하시키고 저장 공간 오버헤드를 증가시킵니다. 이는 엔진이 쿼리와 조인을 처리할 때 문자열의 각 문자를 하나씩 비교하는 반면, 숫자 타입의 경우는 한 번만 비교하면 되기 때문입니다.



18. char/nchar 대신 varchar/nvarchar를 최대한 사용하세요. 첫째, 필드 저장 공간이 길수록 저장 공간을 절약할 수 있고, 둘째로 쿼리의 경우 비교적 작은 필드에서 검색 효율이 당연히 더 높기 때문입니다.



19. 어디서든 select * from t를 사용하지 말고, "*"를 특정 필드 목록으로 대체하며, 사용하지 않는 필드는 반환하지 마세요.



20. 임시 테이블 대신 테이블 변수를 사용해 보세요. 테이블 변수에 많은 데이터를 담고 있다면, 인덱스가 매우 제한적임을 유의하세요(기본 키 인덱스만 포함).



21. 임시 테이블을 자주 생성하고 삭제하는 것을 피하여 시스템 테이블 자원 소비를 줄이세요.

22. 임시 테이블은 사용 불가능한 것이 아니며, 적절히 사용하면 예를 들어 큰 테이블이나 자주 사용되는 테이블에서 데이터셋을 반복적으로 참조해야 할 때 일부 루틴이 더 효과적일 수 있습니다. 하지만 일회성 이벤트의 경우에는 내보내기 테이블을 사용하는 것이 가장 좋습니다.



23. 임시 테이블을 생성할 때, 한 번에 삽입되는 데이터 양이 많다면, 많은 로그를 피하기 위해 '테이블 생성' 대신 선택(select in)을 사용하여 속도를 높일 수 있습니다; 데이터 양이 크지 않다면, 시스템 테이블의 자원을 덜 사용하기 위해 먼저 테이블을 만들고 그 다음에 삽입해야 합니다.



24. 임시 테이블을 사용할 경우, 저장 프로시저 끝에 모든 임시 테이블을 명시적으로 삭제하고, 먼저 테이블을 잘라낸 후 테이블을 삭제하여 시스템 테이블이 장기간 잠기는 것을 방지해야 합니다.



25. 커서 사용은 피하세요. 커서의 효율이 낮기 때문에, 커서가 조작하는 데이터가 10,000줄을 초과하면 다시 쓰는 것을 고려해야 합니다.



26. 커서 기반 또는 임시 테이블 방법을 사용하기 전에 문제 해결을 위해 집합 기반 해법을 찾아야 하며, 이 방법이 더 효과적인 경우가 많습니다.



27. 임시 테이블과 마찬가지로 커서도 사용할 수 없는 것은 아닙니다. 작은 데이터셋FAST_FORWARD 커서를 사용하는 것이 다른 행별 처리 방법보다 더 좋은 경우가 많습니다. 특히 필요한 데이터를 얻기 위해 여러 테이블을 참조해야 할 때는 더욱 그렇습니다. 결과 집합에 "total"을 포함하는 루틴은 보통 커서로 실행하는 루틴보다 빠릅니다. 개발 시간이 허락한다면, 커서 기반과 집합 기반 방법 모두 시도해 보며 어느 쪽이 더 효과적인지 확인할 수 있습니다.



28. 모든 저장 프로시저와 트리거의 시작 부분에 SET NOCOUNT ON을, 끝에 SET NOCOUNT OFF를 설정하세요. 저장 프로시저와 트리거의 각 문장을 실행한 후 클라이언트에게 DONE_IN_PROC 메시지를 보낼 필요가 없습니다.



29. 대규모 트랜잭션 연산을 피하고 시스템의 동시성 용량을 개선하라.



30. 대용량 데이터를 고객에게 반환하지 않도록 주의하세요. 데이터 양이 너무 크면 해당 수요가 합리적인지 고려해야 합니다.




이전의:Xen 4.1.2 가상 머신을 사용하는 CentOS 6.5 시스템
다음:SQL Server 쿼리 속도를 향상시키는 방법
면책 조항:
Code Farmer Network에서 발행하는 모든 소프트웨어, 프로그래밍 자료 또는 기사는 학습 및 연구 목적으로만 사용됩니다; 위 내용은 상업적 또는 불법적인 목적으로 사용되지 않으며, 그렇지 않으면 모든 책임이 사용자에게 부담됩니다. 이 사이트의 정보는 인터넷에서 가져온 것이며, 저작권 분쟁은 이 사이트와는 관련이 없습니다. 위 내용은 다운로드 후 24시간 이내에 컴퓨터에서 완전히 삭제해야 합니다. 프로그램이 마음에 드신다면, 진짜 소프트웨어를 지원하고, 등록을 구매하며, 더 나은 진짜 서비스를 받아주세요. 침해가 있을 경우 이메일로 연락해 주시기 바랍니다.

Mail To:help@itsvse.com