복붙노트

[SQL] SQL에서의 나쁜 성능을 위해인가?

SQL

SQL에서의 나쁜 성능을 위해인가?

내가 좋아하는 일을하고 쿼리를 가지고 :

SELECT FieldX, FieldY FROM A
WHERE FieldW IN (108, 109, 113, 138, 146, 160,
307, 314, 370, 371, 441, 454 ,457, 458, 479, 480,
485, 488, 490, 492, 519, 523, 525, 534, 539, 543,
546, 547, 550, 564, 573, 629, 642, 643, 649, 650,
651, 694, 698, 699, 761, 762, 768, 772, 773, 774,
775, 778, 784, 843, 844, 848, 851, 852, 853, 854,
855, 856, 857, 858, 859, 860, 861, 862, 863, 864,
865, 868, 869, 871, 872, 873, 891) 

너무 많은 옵션과 함께 IN 절을 갖는, 그것은 쿼리 성능에 나쁜? 난 내 응용 프로그램에서 많은 시간 초과가 발생하고있어, 나는 그것이 이런 종류의 문제의 원천이 될 수 있으리라 생각합니다. 나는 좋은 SQL 힌트를 사용하여 숫자를 제거하지 않고 쿼리를 최적화 할 수 있습니까?

편집하다:

@KM이 다른 테이블의 키입니다. 이 간략하게 설명하는 포럼 응용 프로그램입니다 : C #을 응용 프로그램 캐시에 데이터베이스 저장을 모든 포럼을 가져옵니다. C #은 이러한 포럼과이 사용자에 대한 스레드를 유도 할 수있는 프로 시저를 호출하기 전에, C #을은 "모든 포럼"수집, 고려 권한 및 일부 비즈니스 로직을 필터링 일부 로직을 수행합니다. 제한 시간은 데이터베이스가 아닌 응용 프로그램 자체에 발생합니다. 내부 조인과 나는 확실히 내가 절차 내에서 모든 작업을 수행 할 수 있습니다 100 % 아니에요의 쿼리에 모든 로직을 수행하면 많이 필요합니다.

나는 2000 SQL 서버를 사용하고 있습니다

해결법

  1. ==============================

    1.성능에 영향을 미칠 수있는 IN 연산자를 사용하여 쿼리를 작성하는 몇 가지 고려 사항이 있습니다.

    성능에 영향을 미칠 수있는 IN 연산자를 사용하여 쿼리를 작성하는 몇 가지 고려 사항이 있습니다.

    첫째, IN 절은 일반적으로 내부적으로 OR 논리 연산을 사용하는 대부분의 데이터베이스가 다시 작성됩니다. 그래서 COL IN ( 'A', 'B', 'C'가)에 재기록 (COL = 'A') OR (COL = 'B') 또는 (COL = 'C'). 두 쿼리에 대한 실행 계획은 가능성이 COL에 인덱스를 가지고 있다고 가정 상당 할 것이다.

    IN 또는 OR 인수의 변수 번호를 사용하는 경우 둘째, 데이터베이스가 가지고 일으키는 쿼리를 다시 구문 분석하고 때마다 실행 계획을 인수 변화를 다시. 쿼리에 대한 실행 계획을 구축하는 것은 비용이 많이 드는 단계가 될 수 있습니다. 대부분의 데이터베이스는 그들이 키와 정확한 쿼리 텍스트를 사용하여 실행 쿼리에 대한 실행 계획을 캐시합니다. 술어에서 비슷한 쿼리하지만 다른 인수 값을 실행하면 - 당신이 가장 가능성이 데이터베이스는 한 번 구문 분석의 상당한 양 및 구축 실행 계획을 지출하게됩니다. 바인드 변수가 강하게 최적의 쿼리 성능을 보장하는 방법으로 권장되는 이유입니다.

    셋째, 많은 데이터베이스가 실행할 수있는 쿼리의 복잡성에 제한이 - 그 한계 중 하나가 조건에 포함 할 수있는 논리 연산의 수입니다. 귀하의 경우, 수십 값에 도달 할 가능성이있는 데이터베이스의 한계 내장,하지만 당신은 IN 절에 수백 또는 가치의 수천을 통과 할 것으로 예상되는 경우 - 그것은 확실히 발생할 수 있습니다. 이 경우 데이터베이스는 단순히 쿼리 요청을 취소합니다.

    넷째, IN 포함 쿼리 및 OR 술어 항상 최적의 병렬 환경에서 다시 작성할 수 없습니다. MSDN은 병렬 처리에 대한 쿼리를 최적화하는 괜찮은 소개를 가지고 - 병렬 서버 최적화가 적용되지 않는 여러 가지 경우가 있습니다. 일반적으로, 그래도 UNION ALL 연산자를 사용하는 쿼리는 대부분의 데이터베이스에서 하찮게 parrallelizable - 그리고 가능하다면 (OR 및처럼) 논리 연산에 선호된다.

  2. ==============================

    2.당신은 IN이 완벽하게 적합한 것을 사용하여, FieldW에 좋은 색인이있는 경우.

    당신은 IN이 완벽하게 적합한 것을 사용하여, FieldW에 좋은 색인이있는 경우.

    난 그냥 테스트 한과 IN을 사용하는 경우 SQL 2000 클러스터 된 인덱스 스캔을 수행합니다.

  3. ==============================

    3.당신은 임시 테이블을 만들고 그것을 시도에 값을 삽입하고, IN 술어 대신 테이블을 사용할 수 있습니다.

    당신은 임시 테이블을 만들고 그것을 시도에 값을 삽입하고, IN 술어 대신 테이블을 사용할 수 있습니다.

    AFAIK, SQL Server 2000은 SEMI는 해시 조인을 사용하는 가능성의 최적화를 박탈 상수 세트의 해시 테이블을 만들 수 없습니다.

    이것은 당신이 (당신이해야한다) FieldW에 인덱스가없는 경우에만 도움이 될 것입니다.

    또한 인덱스로 FieldX 및 FieldY 열을 포함하도록 시도 할 수 있습니다 :

    CREATE INDEX ix_a_wxy ON a (FieldW, FieldX, FieldY)
    

    쿼리가 인덱스를 사용하여에만 제공 될 수 있도록.

    INDEX를 생성하고이 DML 성능을 약간 저하하지만, 쿼리 성능을 향상시킬 수에 대한 SQL Server 2000은 INCLUDE 옵션이 부족하다.

    최신 정보:

    당신의 실행 계획에서 나는 당신이 복합 인덱스를 필요 이상 참조 (SettingsID, SectionID)

    SQL Server 2000은 참으로 일정 목록에서 해시 테이블을 구축 (그리고 그것을 않습니다)하지만 해시 세미 쿼리 쿼리에 대한 중첩 루프보다 효율적입니다 아마 가입 할 수 있습니다.

    단지 보조 노트 : 당신이 WHERE 조건을 만족하는 행의 수를 알 필요가 있다면, COUNT (열), 대신 사용 COUNT (*)를 사용하지 마십시오.

    카운트 (열)의 열 값이 NULL되는 행을 계산하지 않는다.

    당신의 열이 WHERE 조건을 제공하는 인덱스에 포함되지 않은 경우, 첫째, 둘째, 당신이 기대하지 않은 결과를 얻을 수 있으며이 수단은 최적화 프로그램은 별도의 키 조회 / 북마크 조회를 수행해야합니다.

    ThreadId 클러스터 된 PRIMARY KEY 것으로 보인다 때문에,이 매우 쿼리에 대한 모든 권리, 그러나 일반적으로 그것을 피하려고.

  4. ==============================

    4.데이터 분포에 따라, 귀하의 WHERE 절에 추가 조건은 성능을 향상시킬 수 있습니다. 예를 들어, 식별자의 세트가 테이블의 총 수에 상대적으로 작은, 당신은 IDS는 (아마도 그들은 일반적으로 최근에 추가 될 것입니다, 따라서 범위의 하이 엔드 클러스터) 비교적 가까운 곳에 있다는 것을 알고 있다면, 당신은 (C # 코드에 세트에 최소 및 최대 ID를 결정한 후) 시도 "109과 891 사이 FieldW"술어를 포함 할 수있다. 그것은 그 컬럼에 대한 범위 스캔 (인덱스 경우) 일을하는 것은 빠른 현재 사용중인 것보다 작동 할 수있다.

    데이터 분포에 따라, 귀하의 WHERE 절에 추가 조건은 성능을 향상시킬 수 있습니다. 예를 들어, 식별자의 세트가 테이블의 총 수에 상대적으로 작은, 당신은 IDS는 (아마도 그들은 일반적으로 최근에 추가 될 것입니다, 따라서 범위의 하이 엔드 클러스터) 비교적 가까운 곳에 있다는 것을 알고 있다면, 당신은 (C # 코드에 세트에 최소 및 최대 ID를 결정한 후) 시도 "109과 891 사이 FieldW"술어를 포함 할 수있다. 그것은 그 컬럼에 대한 범위 스캔 (인덱스 경우) 일을하는 것은 빠른 현재 사용중인 것보다 작동 할 수있다.

  5. ==============================

    5.이 코드 그것에 더 나은 방법이 있지만, 나는 그것이 단지 SELECT의 경우 특히, 당신의 시간 제한의 원인 의심. 당신은 당신의 쿼리를 추적하지만보고 그것을 판단 할 수 있어야한다. 그러나이 레코딩은 추측에 의해 최적화 및 그에서 가능성이 추측 될 것이다.

    이 코드 그것에 더 나은 방법이 있지만, 나는 그것이 단지 SELECT의 경우 특히, 당신의 시간 제한의 원인 의심. 당신은 당신의 쿼리를 추적하지만보고 그것을 판단 할 수 있어야한다. 그러나이 레코딩은 추측에 의해 최적화 및 그에서 가능성이 추측 될 것이다.

    의 실제 시간 초과 된 쿼리에 대한 쿼리 계획을 시작하자. 당신은이 조회되는 확실히 알 수 있습니까?

  6. ==============================

    6.IN 정확히 관찰 보고서의 큰 목록을 작성 같은 일이다. 그리고 또는 자주 인덱스가 무시 될 수 있도록 쿼리 unSARGable하게하고 계획은 전체 검사에 간다.

    IN 정확히 관찰 보고서의 큰 목록을 작성 같은 일이다. 그리고 또는 자주 인덱스가 무시 될 수 있도록 쿼리 unSARGable하게하고 계획은 전체 검사에 간다.

  7. ==============================

    7.일반적으로 IN 절 성능에 유해한,하지만 "나쁜는"당신은 무엇이 최선인지 확인하기 위해 자신의 응용 프로그램을 테스트해야하는 등 응용 프로그램, 데이터, 데이터베이스 크기에 따라 달라집니다.

    일반적으로 IN 절 성능에 유해한,하지만 "나쁜는"당신은 무엇이 최선인지 확인하기 위해 자신의 응용 프로그램을 테스트해야하는 등 응용 프로그램, 데이터, 데이터베이스 크기에 따라 달라집니다.

  8. ==============================

    8.기본적으로 어떤 조항이하는 곳 "FieldW = 108 또는 FieldW = 109 또는 FieldW = 113 ..."이다. 때때로 당신은 여러 선택을하고, 노조로 결합하여 더 나은 성능을 얻을 수 있습니다. 예를 들면 :

    기본적으로 어떤 조항이하는 곳 "FieldW = 108 또는 FieldW = 109 또는 FieldW = 113 ..."이다. 때때로 당신은 여러 선택을하고, 노조로 결합하여 더 나은 성능을 얻을 수 있습니다. 예를 들면 :

    SELECT FieldX, FieldY FROM A WHERE FieldW = 108
    UNION ALL
    SELECT FieldX, FieldY FROM A WHERE FieldW = 109
    

    당신은 너무 많은 값을 비교하는 때 물론 그것은 비현실적이다.

    또 다른 옵션은 임시 테이블에 테이블입니다 가입 후 임시 테이블에 그 값을 삽입 할 수 있습니다.

  9. ==============================

    9.이 문을 사용할 때 테이블의 크기는 속도를 결정합니다. 그것은 매우 큰 테이블이 아니라면 ...이 문장은 성능에 영향을 미치지하지 않습니다.

    이 문을 사용할 때 테이블의 크기는 속도를 결정합니다. 그것은 매우 큰 테이블이 아니라면 ...이 문장은 성능에 영향을 미치지하지 않습니다.

  10. ==============================

    10.여기에 귀하의 대답은 ...

    여기에 귀하의 대답은 ...

    http://www.4guysfromrolla.com/webtech/031004-1.shtml

    기본적으로, 당신은 문자열을 분할하고 분할 내용으로 임시 테이블을 채우는 함수를 만들려고합니다. 그런 다음 그 임시 테이블에 가입하고 데이터를 조작 할 수 있습니다. 위의 꽤 잘 일을 설명합니다. 나는이 방법을 많이 사용합니다.

    특정 경우 사용에서 훨씬 빠르게 대신 절에서의 임시 테이블에 가입 할 수 있습니다.

  11. ==============================

    11.성능은 당신이 뭘 하려는지의 맥락에서 판단 할 수있다. 단일 값을 검색의 70 배 기간 같은 것을 기대할 수 있으므로이 경우에는, (어떤것 고유 값입니다 가정) 약 70 행의 검색을 요청하고 있습니다. 그것은 캐싱, 또는 과정에 덜 인해 수 있습니다.

    성능은 당신이 뭘 하려는지의 맥락에서 판단 할 수있다. 단일 값을 검색의 70 배 기간 같은 것을 기대할 수 있으므로이 경우에는, (어떤것 고유 값입니다 가정) 약 70 행의 검색을 요청하고 있습니다. 그것은 캐싱, 또는 과정에 덜 인해 수 있습니다.

    그러나 쿼리 최적화가 필요하거나 경우의 performace가 동일한 액세스 플랜을 통해 단일 값을 검색하는 것보다 약간 다를 수있는 값을 검색하기 위해 전체 테이블 스캔을 수행 할 것인지를 선택할 수 있습니다.

  12. ==============================

    12.당신보다 다른 일을 사용할 수있는 경우 : (: 나는 쉽게 존재로 교체 할 수 있으며이 빠르다 나는 어떤 경우에 좋은 방법 정말을 IN을 사용하고 있었다) 그것을 할

    당신보다 다른 일을 사용할 수있는 경우 : (: 나는 쉽게 존재로 교체 할 수 있으며이 빠르다 나는 어떤 경우에 좋은 방법 정말을 IN을 사용하고 있었다) 그것을 할

    귀하의 경우 : 그것은 그리 나쁜 것 같다.

  13. ==============================

    13.당신은 뭔가를 시도 할 수 있습니다 :

    당신은 뭔가를 시도 할 수 있습니다 :

    select a.FieldX, a.FieldY
    from (
        select FieldW = 108 union
        select FieldW = 109 union
        select FieldW = 113 union
        ...
        select FieldW = 891
    ) _a
    join A a on a.FieldW = _a.FieldW
    

    이 같은 동적 단일 SQL 문을 생성 할 때와 같이 사용자의 상황에 적합 할 수있다. A와 _a 사이에 조인의 행 FieldW 값의 소수 (5)과 많은 수의 (10)와 함께 테스트 내 컴퓨터 (SQL 서버 2008 익스프레스)에서이 사용하는 인덱스가 중첩 된 루프와의 추구, 이는 당신이 찾고있는 아마 것입니다.

  14. ==============================

    14.나는 일반적으로 이런 쿼리에 대한 사용자 정의 테이블 형식을 사용합니다.

    나는 일반적으로 이런 쿼리에 대한 사용자 정의 테이블 형식을 사용합니다.

    CREATE TYPE [dbo].[udt_int] AS TABLE (
        [id] [int] NOT NULL
    )
    

    테이블 변수를 사용하여 숫자의 각 행으로 충전 할 수있다 :

    SELECT 
        FieldX, 
        FieldY
    FROM A
    INNER JOIN @myIds B ON
        A.FieldW = B.id
    
  15. from https://stackoverflow.com/questions/1013797/is-sql-in-bad-for-performance by cc-by-sa and MIT license