source

SQL 퍼포먼스:순서 사용 시 OR 사용 속도가 IN보다 느립니다.

gigabyte 2023. 2. 1. 21:51
반응형

SQL 퍼포먼스:순서 사용 시 OR 사용 속도가 IN보다 느립니다.

MariaDB 10.0.21을 사용하고 있으며 1200만 행에 대해 다음과 같은 쿼리를 실행하고 있습니다.

SELECT 
    `primary_key` 
FROM 
    `texas_parcels` 
WHERE 
    `zip_code`
         IN ('28461', '48227', '60411', '65802', '75215', '75440', '75773', '75783', '76501', '76502', '76504', '76511', '76513', '76518', '76519', '76520', '76522', '76525', '76527', '76528', '76530', '76537', '76539', '76541', '76542', '76543', '76548', '76549', '76550', '76556', '76567', '76571', '76574', '76577', '76578', '76642', '76704', '76853', '77418', '77434', '77474', '77833', '77835', '77836', '77845', '77853', '77879', '77964', '77975', '78002', '78003', '78006', '78013', '78028', '78056', '78064', '78070', '78114', '78123', '78130', '78132', '78133', '78154', '78155', '78359', '78382', '78602', '78605', '78606', '78607', '78608', '78609', '78610', '78611', '78612', '78613', '78614', '78615', '78616', '78617', '78619', '78620', '78621', '78623', '78624', '78626', '78628', '78629', '78632', '78633', '78634', '78636', '78638', '78639', '78640', '78641', '78642', '78643', '78644', '78645', '78648', '78650', '78652', '78653', '78654', '78655', '78656', '78657', '78659', '78660', '78662', '78663', '78664', '78665', '78666', '78669', '78672', '78676', '78681', '78699', '78701', '78702', '78703', '78704', '78705', '78717', '78719', '78721', '78722', '78723', '78724', '78725', '78726', '78727', '78728', '78729', '78730', '78731', '78732', '78733', '78734', '78735', '78736', '78737', '78738', '78739', '78741', '78744', '78745', '78746', '78747', '78748', '78749', '78750', '78751', '78752', '78753', '78754', '78756', '78757', '78758', '78759', '78828', '78934', '78940', '78941', '78942', '78945', '78946', '78947', '78948', '78953', '78954', '78956', '78957', '78963', '92536') 
ORDER BY 
    `timestamp_updated` ASC
LIMIT 1000;

는 복복 on a i의 복합 지수를 .(zip_code,timestamp_updated)최대 1.6초 안에 결과를 얻을 수 있습니다.다음 쿼리에서는 같은 우편번호를 계속 표시하고 있지만 IN() 대신 OR을 사용하고 있습니다.

SELECT 
    `primary_key`
FROM 
    `texas_parcels` 
WHERE
(`zip_code` = '28461' OR `zip_code` = '48227' OR `zip_code` = '60411' OR `zip_code` = '65802' OR `zip_code` = '75215' OR `zip_code` = '75440' OR `zip_code` = '75773' OR `zip_code` = '75783' OR `zip_code` = '76501' OR `zip_code` = '76502' OR `zip_code` = '76504' OR `zip_code` = '76511' OR `zip_code` = '78957' OR `zip_code` = '78963' OR `zip_code` = '92536' OR `zip_code` = '76513' OR `zip_code` = '76518' OR `zip_code` = '76519' OR `zip_code` = '76520' OR `zip_code` = '76522' OR `zip_code` = '76525' OR `zip_code` = '76527' OR `zip_code` = '76528' OR `zip_code` = '76530' OR `zip_code` = '76537' OR `zip_code` = '76539' OR `zip_code` = '76541' OR `zip_code` = '76542' OR `zip_code` = '76543' OR `zip_code` = '76548' OR `zip_code` = '76549' OR `zip_code` = '76550' OR `zip_code` = '76556' OR `zip_code` = '76567' OR `zip_code` = '76571' OR `zip_code` = '76574' OR `zip_code` = '76577' OR `zip_code` = '76578' OR `zip_code` = '76642' OR `zip_code` = '76704' OR `zip_code` = '76853' OR `zip_code` = '77418' OR `zip_code` = '77434' OR `zip_code` = '77474' OR `zip_code` = '77833' OR `zip_code` = '77835' OR `zip_code` = '77836' OR `zip_code` = '77845' OR `zip_code` = '77853' OR `zip_code` = '77879' OR `zip_code` = '77964' OR `zip_code` = '77975' OR `zip_code` = '78002' OR `zip_code` = '78003' OR `zip_code` = '78006' OR `zip_code` = '78013' OR `zip_code` = '78028' OR `zip_code` = '78056' OR `zip_code` = '78064' OR `zip_code` = '78070' OR `zip_code` = '78114' OR `zip_code` = '78123' OR `zip_code` = '78130' OR `zip_code` = '78132' OR `zip_code` = '78133' OR `zip_code` = '78154' OR `zip_code` = '78155' OR `zip_code` = '78359' OR `zip_code` = '78382' OR `zip_code` = '78602' OR `zip_code` = '78605' OR `zip_code` = '78606' OR `zip_code` = '78607' OR `zip_code` = '78608' OR `zip_code` = '78609' OR `zip_code` = '78610' OR `zip_code` = '78611' OR `zip_code` = '78612' OR `zip_code` = '78613' OR `zip_code` = '78614' OR `zip_code` = '78615' OR `zip_code` = '78616' OR `zip_code` = '78617' OR `zip_code` = '78619' OR `zip_code` = '78620' OR `zip_code` = '78621' OR `zip_code` = '78623' OR `zip_code` = '78624' OR `zip_code` = '78626' OR `zip_code` = '78628' OR `zip_code` = '78629' OR `zip_code` = '78632' OR `zip_code` = '78633' OR `zip_code` = '78634' OR `zip_code` = '78636' OR `zip_code` = '78638' OR `zip_code` = '78639' OR `zip_code` = '78640' OR `zip_code` = '78641' OR `zip_code` = '78642' OR `zip_code` = '78643' OR `zip_code` = '78644' OR `zip_code` = '78645' OR `zip_code` = '78648' OR `zip_code` = '78650' OR `zip_code` = '78652' OR `zip_code` = '78653' OR `zip_code` = '78654' OR `zip_code` = '78655' OR `zip_code` = '78656' OR `zip_code` = '78657' OR `zip_code` = '78659' OR `zip_code` = '78660' OR `zip_code` = '78662' OR `zip_code` = '78663' OR `zip_code` = '78664' OR `zip_code` = '78665' OR `zip_code` = '78666' OR `zip_code` = '78669' OR `zip_code` = '78672' OR `zip_code` = '78676' OR `zip_code` = '78681' OR `zip_code` = '78699' OR `zip_code` = '78701' OR `zip_code` = '78702' OR `zip_code` = '78703' OR `zip_code` = '78704' OR `zip_code` = '78705' OR `zip_code` = '78717' OR `zip_code` = '78719' OR `zip_code` = '78721' OR `zip_code` = '78722' OR `zip_code` = '78723' OR `zip_code` = '78724' OR `zip_code` = '78725' OR `zip_code` = '78726' OR `zip_code` = '78727' OR `zip_code` = '78728' OR `zip_code` = '78729' OR `zip_code` = '78730' OR `zip_code` = '78731' OR `zip_code` = '78732' OR `zip_code` = '78733' OR `zip_code` = '78734' OR `zip_code` = '78735' OR `zip_code` = '78736' OR `zip_code` = '78737' OR `zip_code` = '78738' OR `zip_code` = '78739' OR `zip_code` = '78741' OR `zip_code` = '78744' OR `zip_code` = '78745' OR `zip_code` = '78746' OR `zip_code` = '78747' OR `zip_code` = '78748' OR `zip_code` = '78757' OR `zip_code` = '78758' OR `zip_code` = '78759' OR `zip_code` = '78828' OR `zip_code` = '78934' OR `zip_code` = '78940' OR `zip_code` = '78941' OR `zip_code` = '78942' OR `zip_code` = '78945' OR `zip_code` = '78946' OR `zip_code` = '78947' OR `zip_code` = '78948' OR `zip_code` = '78953' OR `zip_code` = '78954' OR `zip_code` = '78956')
ORDER BY 
    `timestamp_updated` ASC
LIMIT 1000;

이 두 번째 쿼리는 동일한 순서로 약 7.8초 동안 동일한 결과를 가져옵니다.설명을 통해 각 쿼리를 실행할 때는 거의 동일하지만 약간 다릅니다.rowssumediscloss.discloss를 합니다.

id  select_type     table        type      possible_keys          key            key_len    ref        rows       filtered              Extra
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1     SIMPLE     TX_Property   range    Zip Code Search     Zip Code Search       15     (NULL)      2402699     99.88      Using where; Using index; Using filesort  
 2     SIMPLE     TX_Property   range    Zip Code Search     Zip Code Search       15     (NULL)      2321908     99.91      Using where; Using index; Using filesort 

때 것은 " " " 입니다.Sorting Result시간, 두 번째 쿼리에서는 최대 7.2초가 소요되었습니다.

제가 이해할 수 없는 것은 어떻게 다른 오퍼레이터가 순서상 그렇게 큰 차이를 만들 수 있는가 하는 것입니다.실행 시간에 큰 차이가 있으면 의미가 있을까요?프로파일링이 어떻게 이루어지는지 정확히 알 수 없고, 실제로는 그 부분을 실행하는 시간일 뿐인데, 복잡한 방식으로 라벨이 붙여진 것일 수도 있습니다.

, 「 」를 제외하고 했을 때, 「 」의 「 」를 참조해 .ORDER BY timestamp_updated ASC첫 번째 쿼리는 0.106초, 두 번째 쿼리는 0.157초 정도 소요되었습니다.

의 삭제ORDER BY1000행만 지나면 정지할 수 있기 때문에 훨씬 더 빨리 실행됩니다.행이 OR/IN과 합니까?OR/IN은 몇 입니까?

해 주세요.EXPLAINs가 문문 that that that that that라고 Using index ' 지수를 뜻입니다.입니다.SELECT하나의 인덱스에 있습니다.

암묵적으로 되어 있기 때문에 InnoDB는 PK가 포함되어 .INDEX(zip_code, timestamp_updated)하게 「」입니다.INDEX(zip_code, timestamp_updated, primaryKey)

는 (1)OR, (2 BY (1) IN 또는 OR, (2) ORDER BY의 두 가지 하지 않은 인덱스로 처리할 수 있는 것은 둘 중 하나뿐입니다.하면 "인덱스"를 사용할 수 .zip_code.

  1. 는 인덱스에서 이러한 zipcode 중 하나와 일치하는 행을 찾습니다.
  2. 타임스탬프와 pk를 수집하여 3개의 열을 tmp 테이블에 저장합니다.
  3. 분류하다
  4. 는 첫 번째 1000을 전달합니다.

당신이 '만약에'라고 말했다면INDEX(timestamp_updated, zip_code)여전히 '커버링' 인덱스를 사용할 수 있지만, 이 플레이버에서는 인덱스가 SORT를 필요로 하지 않게 됩니다.「1000」입니다.동작 방법은 다음과 같습니다.

  1. 인덱스를 타임스탬프 순서로 스캔합니다.
  2. 각 행이 해당 zip 중 하나인지 확인합니다(여기서 테스트가 IN 형식으로 더 빠를 수 있습니다).
  3. 일치하는 경우 행을 전달하고, 1000인 경우 중지합니다.

근데 잠깐만...이제 당신은 1,200만 줄에 좌우됩니다.이러한 zip이 있는 1000 행이 조기에 발생하는 경우(오래된 타임스탬프), 빠르게 정지할 수 있습니다.1000을 찾기 위해 모든 행을 확인해야 하는 경우(또는 1000도 없는 경우) 전체 인덱스 검색이며 인덱스의 배열이 '잘못됨'입니다.

에게 둘 다 INDEXes부적절한 정보(값의 분포 없음)에 근거해, 충실한 선택을 실시해, 나쁜 것을 선택할 가능성이 있습니다.

사실상 2차원 지표가 필요합니다.그런 건 없어 (스페셜이 갇혔을 수도 있지 않을까?)그렇지만.....

PARTITION BY RANGE(timestamp)★★★★★★★★★★★★★★★와 함께INDEX zip으로 시작하는 것이 더 나을 수 있습니다.그러나 옵티마이저가 첫 번째 파티션에서 1000개의 행을 발견하면 종료할 수 있다는 것을 알 수 있을 만큼 똑똑한지는 의문입니다.그리고 1000개의 결과가 나오지 않으면 여전히 크게 실패합니다.

PARTITION BY RANGE(zip)★★★★★★★★★★★★★★★와 함께INDEX 타임스탬프로 시작하는 것은 아마 도움이 되지 않을 것이다. 왜냐하면 그 많은 집들은 많은 가지치기 작업을 하지 않을 것이기 때문이다.

★★★★★★★★★★★를 입력해 주세요.EXPLAIN FORMAT=JSON SELECT...;각 시도에 대해 설명하겠습니다.시간적 변화를 설명할 몇 가지 미묘한 단서가 있을지도 모른다.

각 타이밍을 두 번 실행했습니까?(그렇지 않으면 캐시에 의해 결과가 색칠되었을 수 있습니다).

또 다른 접근법

이것이 얼마나 잘 기능할지는 모르겠지만, 다음과 같습니다.

SELECT  primary_key
    FROM  ( 
              ( SELECT  primary_key, timestamp_updated
                    FROM  texas_parcels
                    WHERE  zip_code = '28461'
                    ORDER BY  timestamp_updated
                    LIMIT  1000 
              )
            UNION  ALL (
                SELECT  primary_key, timestamp_updated
                    FROM  texas_parcels
                    WHERE  zip_code = '48227'
                    ORDER BY  timestamp_updated
                    LIMIT  1000 
                       )
            UNION  ALL (
                SELECT  primary_key, timestamp_updated
                    FROM  texas_parcels
                    WHERE  zip_code = '60411'
                    ORDER BY  timestamp_updated
                    LIMIT  1000 ) ... 
          ) x
    ORDER BY  timestamp_updated
    LIMIT  1000 

것 같다x에는, 1130 행이 , 행 밖에 . ★★★★★★★★★★★★★★★★★.UNION다음 사항에 주의:LIMIT각 서브쿼리 및 외부 쿼리에 포함되어 있습니다.OFFSET츠키노

비교하고 있는 우편번호 목록이 꽤 길군요.MySQL에는 없는 실행 시간이 조금 다른 이유에 영향을 주는 최적화가 있습니다.MySQL은 상수 목록을 사용하여 목록을 정렬하고 이진 검색을 수행합니다.나는 이것이 마지막 결과를 설명하는 것을 볼 수 있었다.

order by실제 실행은 서버에서 실행 중인 다른 작업에 의해 영향을 받을 수 있습니다.른른른른른른른른른른른?????

MYSQL 에는 최적화가 있습니다.OR 를 사용하는 경우는, 비교의 수가 증가합니다.

언급URL : https://stackoverflow.com/questions/32256402/sql-performance-using-or-is-slower-than-in-when-using-order-by

반응형