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만큼 늘릴 수 있습니다.
대신 할 수 있는 일은 다음과 같습니다.
- 데이터 세트의 마지막 ID(30)를 유지합니다(예: lastId = 530).
- 조건을 추가합니다.
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
'source' 카테고리의 다른 글
| MySQL 인덱스 - 모범 사례는 무엇입니까? (0) | 2023.01.06 |
|---|---|
| PHP에서 HTML/XML을 어떻게 해석하고 처리합니까? (0) | 2023.01.06 |
| JSON에서 새로운 회선을 처리하려면 어떻게 해야 합니까? (0) | 2023.01.06 |
| 여러 콘텍스트 매니저에 "with" 블록을 생성하시겠습니까? (0) | 2023.01.06 |
| API를 이용하여 인스타그램에 사진을 올리는 방법 (0) | 2023.01.06 |
