source

MYSQL의 LIMIT 값이 클수록 쿼리가 느려지는 이유는 무엇입니까?

bestscript 2023. 1. 6. 19:53

MYSQL의 LIMIT 값이 클수록 쿼리가 느려지는 이유는 무엇입니까?

시나리오 요약: 1600만 개 이상의 레코드가 있는 테이블 [2GB 크기]SELECT에서 LIMIT 오프셋이 클수록 ORDER BY *primary_key*를 사용하는 경우 쿼리가 느려집니다.

그렇게

SELECT * FROM large ORDER BY `id`  LIMIT 0, 30 

보다 훨씬 적게 걸린다

SELECT * FROM large ORDER BY `id` LIMIT 10000, 30 

그건 30장의 음반만 주문하는 거고 어느 쪽이든 마찬가지야ORDER BY의 오버헤드가 아닙니다.
이제 최신 30개의 행을 가져올 때 약 180초가 소요됩니다.어떻게 하면 이 간단한 쿼리를 최적화할 수 있을까요?

나도 똑같은 문제가 있었어.특정 세트의 30이 아닌 대량의 데이터를 수집하려는 경우 루프를 실행하고 오프셋을 30만큼 늘릴 수 있습니다.

대신 할 수 있는 일은 다음과 같습니다.

  1. 데이터 세트의 마지막 ID(30)를 유지합니다(예: lastId = 530).
  2. 조건을 추가합니다.WHERE id > lastId limit 0,30

따라서 항상 ZERO 오프셋을 가질 수 있습니다.성능 향상에 놀라실 겁니다.

쿼리는 첫 번째 오프셋을 카운트오프해야 하므로 오프셋이 클수록 쿼리가 느려지는 것이 일반적입니다.OFFSET + LIMIT레코드(및 테이크 온리)LIMIT그 중 하나).이 값이 클수록 조회가 실행되는 시간이 길어집니다.

쿼리는 다음 주소로 바로 이동할 수 없습니다.OFFSET첫째, 레코드의 길이가 다를 수 있고 둘째, 삭제된 레코드와 간격이 있을 수 있기 때문입니다.가는 길에 각 기록을 확인하고 세야 합니다.

라고 가정하면id는 MyISAM 테이블의 프라이머리 키 또는 InnoDB 테이블의 고유한 비프라이머리 키필드입니다.다음 트릭을 사용하여 속도를 높일 수 있습니다.

SELECT  t.* 
FROM    (
        SELECT  id
        FROM    mytable
        ORDER BY
                id
        LIMIT 10000, 30
        ) q
JOIN    mytable t
ON      t.id = q.id

다음 문서를 참조하십시오.

MySQL은 이와 같이 포장/주문되어 있다고 가정할 수 없기 때문에(또는 1 ~10000의 연속된 값을 가지고 있다고 가정할 수 없기 때문에) 10000번째 레코드(또는 제안대로 80000번째 바이트)로 직접 이동할 수 없습니다.실제로는 그럴 수 있지만 MySQL에서는 홀/갭/삭제된 ID가 없다고 가정할 수 없습니다.

따라서 bobs가 기술한 바와 같이 MySQL은 10,000개의 행을 가져와야 합니다(또는 인덱스의 10000번째 엔트리를 통과해야 합니다).id30명을 찾기 전에)을 클릭합니다.

EDIT : 포인트 설명하려면

주의해 주세요.

SELECT * FROM large ORDER BY id LIMIT 10000, 30 

느릴 거예요.

SELECT * FROM large WHERE id >  10000 ORDER BY id LIMIT 30 

빠름(er)이 없을 경우 같은 결과를 반환한다.idsi. 갭)s(즉, 갭)

SELECT 쿼리를 ORDER BY ID LIMIT X,Y로 최적화하는 흥미로운 예를 찾았습니다.행 수가 3500만 개이므로 행 범위를 찾는 데 2분 정도 소요되었습니다.

요령은 다음과 같습니다.

select id, name, address, phone
FROM customers
WHERE id > 990
ORDER BY id LIMIT 1000;

마지막 ID에 WHERE를 넣으면 성능이 크게 향상됩니다.저는 2분에서 1초 정도였어요:)

기타 재미있는 요령: http://www.iheavy.com/2013/06/19/3-ways-to-optimize-for-paging-in-mysql/

스트링으로도 동작합니다.

두 쿼리의 시간은 테이블에서 행을 검색하는 중입니다.2개의 쿼리에서 시간이 걸리는 부분은 테이블에서 행을 검색하는 것입니다. Logically speaking, in the 논리적으로 말하면LIMIT 0, 30버전만 검색해야 합니다.버전. 30행만 검색하면 됩니다.서서 LIMIT 10000, 301만 명 30만 명데이터 읽기 프로세스를 최적화할 수 있지만 다음 사항을 고려하십시오.

쿼리에 WHERE 절이 있다면?엔진은 적격인 모든 행을 반환하고 데이터를 정렬한 후 최종적으로 30 행을 가져옵니다.

행이 ORDER BY 순서로 처리되지 않는 경우도 고려하십시오.반환할 행을 결정하려면 모든 한정 행을 정렬해야 합니다.

비교 및 수치를 알고 싶은 분:)

실험 1: 데이터 집합에는 약 1억 개의 행이 포함되어 있습니다.각 행에는 여러 개의 BIGINT, TINYINT 및 약 1k자를 포함하는 2개의 TEXT 필드가 포함됩니다.

  • := 란 : : =SELECT * FROM post ORDER BY id LIMIT {offset}, 5
  • 오 @ : = @Quassnoi 。 SELECT t.* FROM (SELECT id FROM post ORDER BY id LIMIT {offset}, 5) AS q JOIN post t ON t.id = q.id
  • 세 세 번째 방법, 세 번째 방법은요.... WHERE id>xxx LIMIT 0,5는 고정시간이어야 하므로 여기에 표시되지 않습니다.

실험 2: 한 행에 BIGINT가 3개뿐이라는 점만 빼면 비슷합니다.

  • 녹색 : = 이전 파란색
  • 빨간색 : = 이전 주황색

여기에 이미지 설명 입력

언급URL : https://stackoverflow.com/questions/4481388/why-does-mysql-higher-limit-offset-slow-the-query-down