will_paginate 사용 : 긴 쿼리를 개선하기 위해 Total_entries
-
07-07-2019 - |
문제
현재 구현이 있습니다 will_paginate 그것을 사용합니다 Paginate_by_sql 수집품을 구축하는 방법. 사용자 정의 쿼리가 있습니다 Total_entries 그것은 매우 복잡하고 DB에 큰 하중을줍니다. 따라서 우리는 Potal_entries를 Pagination에서 완전히 자르고 싶습니다.
다시 말해, '이전 1 [2] 3 4 5 다음'의 일반적인 페이지 매김 표시 대신, 우리는 단순히 '다음 - 이전'버튼 만 좋아할 것입니다. 그러나 우리는 몇 가지를 알아야합니다.
- 이전 링크를 표시합니까? 이것은 현재 선택에 표시된 기록 이전에 기존 기록이있는 경우에만 발생합니다.
- 다음 링크를 표시합니까? 컬렉션의 마지막 레코드가 표시되면 표시되지 않습니다.
로부터 문서
공급하지 않으면 행을 계산하기위한 쿼리가 자동으로 생성됩니다 : Total_entries. 이 생성 된 SQL에 문제가 발생하면 응용 프로그램에서 수동으로 수를 수행 할 수 있습니다.
따라서 궁극적으로 이상적인 상황은 다음과 같습니다.
- 데이터베이스에 너무 많은 부하가 발생하여 Total_entries 수를 제거합니다.
- 다음/이전 버튼 만 탐색 할 수있는 모든 페이지 번호를 표시 할 필요가없는 반지 만 사용하여 한 번에 50 개의 레코드를 표시합니다.
- 다음 버튼과 이전 버튼 만 표시합니다
비슷한 문제로 일했거나 결의안에 대해 생각한 사람이 있습니까?
해결책
Will_Paginate가 항목 수를 계산하는 데 정말로 끔찍한 작업을 수행하는 경우가 많습니다. 특히 Count SQL 생성기를 혼동하는 조인이있는 경우.
필요한 모든 것이 간단한 이전/다음 방법 만 있으면 데이터베이스에서 n+1 항목을 검색하려고 시도하고 마지막 페이지에있는 것보다 n 이하 만 얻는 경우 만 있으면됩니다.
예를 들어:
per_page = 10
page = 2
@entries = Thing.with_some_scope.find(:all, :limit => per_page + 1, :offset => (page - 1) * per_page)
@next_page = @entries.slice!(per_page, 1)
@prev_page = page > 1
이를 필요로하는 다양한 모델에 포함될 수있는 일부 모듈에서이를 쉽게 캡슐화하거나 컨트롤러 확장을 할 수 있습니다.
이것이 기본 will_paginate 메소드보다 훨씬 더 잘 작동한다는 것을 알았습니다.
유일한 성능 문제는 테이블의 크기에 따라 문제가 될 수있는 MySQL의 제한입니다.
어떤 이유로 든 MySQL에서 작은 제한을 가진 쿼리를 수행하는 데 걸리는 시간은 오프셋에 비례합니다. 사실상 데이터베이스 엔진은 특정 오프셋 값으로 이어지는 모든 행을 읽은 다음 예상대로 건너 뛰지 않고 다음 한도 번호 행을 반환합니다.
100,000 플러스 범위에서 값이 오프셋되는 큰 데이터 세트의 경우 성능 저하가 크게 저하 될 수 있습니다. 이것이 나타나는 방법은 1 페이지가 매우 빠르며 1000 페이지는 다소 느리지 만 2000 페이지는 매우 느립니다.