programing

이중 쿼리 없이 MySQL 페이지 번호 지정

goodjava 2022. 11. 5. 17:47

이중 쿼리 없이 MySQL 페이지 번호 지정

MySQL 쿼리에서 결과 수를 얻는 동시에 결과를 제한하는 방법이 있는지 궁금합니다.

페이지 매김은 처음에 다음과 같은 작업을 수행하는 것으로 알고 있습니다.

query = SELECT COUNT(*) FROM `table` WHERE `some_condition`

num_rows(query)가 있어요. , ㅇㅇㅇㅇㄹㄹㄹㄹㄹㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴ.하지만 실제로 결과를 제한하기 위해 두 번째 질문을 해야 합니다.

query2 = SELECT COUNT(*) FROM `table` WHERE `some_condition` LIMIT 0, 10

제공되는 총 결과 수를 가져오고 단일 쿼리에서 반환되는 결과를 제한할 수 있는 방법이 있습니까?아니면 다른 효율적인 방법이 있을까요?

나는 거의 두 가지 질문을 하지 않는다.

필요한 행보다 하나만 더 반환하고 페이지에 10개만 표시하고 표시된 행보다 많은 행이 있으면 "다음" 버튼을 표시하십시오.

SELECT x, y, z FROM `table` WHERE `some_condition` LIMIT 0, 11
// Iterate through and display 10 rows.
// if there were 11 rows, display a "Next" button.

당신의 질문은 가장 관련성이 높은 순서대로 돌아와야 합니다.대부분의 사람들은 412페이지 중 236페이지로 가는 것에 신경쓰지 않을 것입니다.

구글 검색을 했는데 결과가 첫 페이지에 없으면 9페이지가 아니라 2페이지로 이동합니다.

아니요, 페이지 번호를 매기는 어플리케이션의 수만큼입니다.신뢰성과 방탄성이 뛰어나지만 쿼리를 두 번 실행하지만 카운트를 몇 초 동안 캐시할 수 있으므로 많은 도움이 됩니다.

다른 은 '보다 낫다'를 사용해요.SQL_CALC_FOUND_ROWS합니다.SELECT FOUND_ROWS()거 요.FOUND_ROWS()그 후 콜에 문제가 있습니다.MySQL 에는, 이것에 영향을 주는 버그가 있습니다.ORDER BY큰 테이블에서는 두 쿼리의 단순한 접근 방식보다 훨씬 느립니다.

이중 의 또 다른 을 먼저 두 행만 입니다.COUNT(*)최대 행 수가 검색되었는지 쿼리합니다.

많은 응용 프로그램에서 가장 가능성이 높은 결과는 모든 결과가 한 페이지에 들어맞는 것이며, 페이지 번호 매김은 표준이 아니라 예외입니다.이 경우 첫 번째 쿼리는 최대 수의 결과를 가져오지 않습니다.

예를 들어 Stackoverflow 질문에 대한 답변은 두 번째 페이지에 거의 표시되지 않습니다.답변에 대한 코멘트는 모두 표시하기 위해 필요한 5개 정도를 초과하는 경우가 거의 없습니다.

따라서 이러한 애플리케이션에서는 먼저 LIMIT를 사용하여 쿼리를 수행할 수 있습니다.이 제한에 도달하지 않는 한 몇 개의 행이 있는지 알 수 있습니다.단, 1초도 실행할 필요가 없습니다.COUNT(*)query - 대부분의 상황을 커버합니다.

대부분의 경우 직관에 반하는 것처럼 보이지만 두 개의 개별 쿼리로 수행하는 것이 한 번에 수행하는 것보다 훨씬 빠르고 리소스 소모가 적습니다.

사용하시는 경우SQL_CALC_FOUND_ROWS큰 테이블에서는 쿼리가 매우 느려집니다.두 개의 쿼리를 실행하는 것보다 훨씬 느려집니다.첫 번째 쿼리는COUNT(*)LIMIT가 있는 두 번째.그 이유는SQL_CALC_FOUND_ROWSLIMIT 구를 적용하기 전에 행을 가져오는 대신 LIMIT 구가 적용됩니다.따라서 제한을 적용하기 전에 가능한 모든 결과에 대해 행 전체를 가져옵니다.인덱스는 실제로 데이터를 가져오기 때문에 이 값을 충족할 수 없습니다.

두 가지 쿼리 접근 방식을 사용할 경우 첫 번째 쿼리 접근 방식은 가져오기만 합니다.COUNT(*)실제 데이터를 가져오지 않아도 됩니다. 일반적으로 인덱스를 사용할 수 있고 보는 모든 행에 대해 실제 행 데이터를 가져올 필요가 없기 때문에 훨씬 더 빨리 만족할 수 있습니다.그런 다음 두 번째 쿼리는 첫 번째 쿼리만 보면 됩니다.$offset + $limit행을 지정한 후 돌아갑니다.

MySQL 퍼포먼스 블로그의 이 투고에서는 이에 대해 자세히 설명합니다.

http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/

페이지 배정을 최적화하는 방법에 대한 자세한 내용은 이 게시물과 이 게시물확인하십시오.

2020년에 답을 찾고 있는 사람들을 위해.MySQL 문서에 따르면:

SQL_CALC_FOUND_ROWS 쿼리 수식자 및 그에 부수되는 FOUND_ROWS() 함수는 MySQL 8.0.17 이후 폐지되며 향후 MySQL 버전에서 삭제될 예정입니다.대체 수단으로 LIMIT을 사용하여 쿼리를 실행하고 다음으로 COUNT(*)를 사용하여 LIMIT을 사용하지 않고 두 번째 쿼리를 실행하여 추가 행이 있는지 여부를 확인합니다.

그걸로 해결됐나 보네

답변이 늦어질 수 있지만 두 번째 쿼리(제한 포함)는 건너뛰고 백엔드 스크립트를 통해 정보를 필터링할 수 있습니다.예를 들어 PHP에서는 다음과 같은 작업을 수행할 수 있습니다.

if($queryResult > 0) {
   $counter = 0;
   foreach($queryResult AS $result) {
       if($counter >= $startAt AND $counter < $numOfRows) {
            //do what you want here
       }
   $counter++;
   }
}

그러나 고려해야 할 레코드가 수천 개에 달할 경우 매우 빠르게 비효율적이 됩니다.미리 계산된 카운트를 알아보는 게 좋을 것 같아요

이 주제에 대한 좋은 읽을거리: http://www.percona.com/ppc2009/PPC2009_mysql_pagination.pdf

SELECT col, col2, (SELECT COUNT(*) FROM `table`) / 10 AS total FROM `table` WHERE `some_condition` LIMIT 0, 10

서 ★★★★★10와 「」입니다.0번호입니다. 하면 .pageNumber - 1를 참조해 주세요.

하위 쿼리에서 대부분의 쿼리를 재사용하여 ID로 설정할 수 있습니다.예를 들어, 런타임별로 정렬된 문자 's'가 포함된 동영상을 찾는 동영상 쿼리는 다음과 같습니다.

SELECT Movie.*, (
    SELECT Count(1) FROM Movie
        INNER JOIN MovieGenre 
        ON MovieGenre.MovieId = Movie.Id AND MovieGenre.GenreId = 11
    WHERE Title LIKE '%s%'
) AS Count FROM Movie 
    INNER JOIN MovieGenre 
    ON MovieGenre.MovieId = Movie.Id AND MovieGenre.GenreId = 11
WHERE Title LIKE '%s%' LIMIT 8;

저는 데이터베이스 전문가가 아닙니다.누군가 좀 더 최적화해 주셨으면 합니다.SQL 명령줄 인터페이스에서 바로 실행할 수 있기 때문에 노트북에서는 둘 다 0.02초 정도 걸립니다.

SELECT * 
FROM table 
WHERE some_condition 
ORDER BY RAND()
LIMIT 0, 10

언급URL : https://stackoverflow.com/questions/818567/mysql-pagination-without-double-querying