Programing

MYSQL이 더 높은 LIMIT 오프셋으로 인해 쿼리 속도가 느려지는 이유는 무엇입니까?

crosscheck 2020. 6. 7. 10:30
반응형

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 초가 걸립니다. 간단한 쿼리를 어떻게 최적화 할 수 있습니까?


쿼리가 첫 번째 OFFSET + LIMIT레코드 를 계산하고 LIMIT그중 하나만 가져야 하므로 오프셋이 높을수록 쿼리 속도가 느려집니다 . 이 값이 높을수록 쿼리 실행 시간이 길어집니다.

OFFSET먼저 레코드 길이가 다를 수 있고, 둘째, 삭제 된 레코드와의 간격이있을 수 있기 때문에 쿼리를 바로 진행할 수 없습니다 . 각 레코드를 확인하고 계산해야합니다.

그 가정하면 idA는 PRIMARY KEY(A)의 MyISAM테이블이 트릭을 사용하여 속도를 높일 수 있습니다 :

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

이 기사를 참조하십시오 :


나는 똑같은 문제가 있었다. 특정 30 세트가 아닌 많은 양의 데이터를 수집하려는 경우 루프를 실행하고 오프셋을 30 씩 증가시킬 수 있습니다.

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

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

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


MySQL은 10000 번째 레코드 (또는 제안하는대로 80000 바이트)로 직접 이동할 수 없습니다. 포장 / 정렬 된 것으로 가정 할 수 없기 때문에 (또는 1 ~ 10000의 연속 값이 있다고 가정 할 수 없기 때문에). 실제로는 그럴 수도 있지만 MySQL은 구멍 / 간격 / 삭제 된 ID가 없다고 가정 할 수 없습니다.

bobs가 지적했듯이 MySQL은 id30을 반환하기 전에 10000 개의 행을 가져와야합니다 (또는 인덱스의 10000 번째 항목을 통과 해야 ).

편집 : 내 요점을 설명하기 위해

그럼에도 불구하고

SELECT * FROM large ORDER BY id LIMIT 10000, 30 

느린 (어) ,

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

빠른 (어) 와 같은 결과가 실종이 없음을 제공 반환 id의 (즉, 간격).


SELECT 쿼리 ORDER BY id LIMIT X, Y를 최적화하는 흥미로운 예를 찾았습니다. 나는 35million의 행을 가지고 있으므로 행 범위를 찾는 데 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/

문자열과도 작동합니다.


두 쿼리에서 시간이 많이 걸리는 부분은 테이블에서 행을 검색하는 것입니다. 논리적으로 말하면, LIMIT 0, 30버전에서는 30 개의 행만 검색하면됩니다. 에서 LIMIT 10000, 30버전, 10000 개 행이 평가 30 개 행이 반환됩니다. 데이터 읽기 프로세스에서 일부 최적화를 수행 할 수 있지만 다음을 고려하십시오.

What if you had a WHERE clause in the queries? The engine must return all rows that qualify, and then sort the data, and finally get the 30 rows.

Also consider the case where rows are not processed in the ORDER BY sequence. All qualifying rows must be sorted to determine which rows to return.

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

반응형