복붙노트

LIMIT이 적용되기 전에 결과를 얻는 가장 좋은 방법

PHP

LIMIT이 적용되기 전에 결과를 얻는 가장 좋은 방법

DB에서 오는 데이터를 페이징 할 때 페이지 점프 컨트롤을 렌더링 할 페이지의 수를 알아야합니다.

현재는 쿼리를 두 번 실행하여 총 결과를 결정하기 위해 count ()에 래핑 된 다음 두 번째로 현재 페이지에 필요한 결과 만 가져 오는 데 적용되는 제한이 적용됩니다.

이것은 비효율적 인 것처럼 보인다. LIMIT가 적용되기 전에 반환 된 결과의 수를 결정하는 더 좋은 방법이 있습니까?

나는 PHP와 Postgres를 사용하고있다.

해결법

  1. ==============================

    1.2008 년 이후로 상황이 변경되었습니다. 창 함수를 사용하여 한 번의 쿼리로 전체 개수와 제한된 결과를 얻을 수 있습니다. (2009 년 PostgreSQL 8.4에서 소개되었습니다).

    2008 년 이후로 상황이 변경되었습니다. 창 함수를 사용하여 한 번의 쿼리로 전체 개수와 제한된 결과를 얻을 수 있습니다. (2009 년 PostgreSQL 8.4에서 소개되었습니다).

    SELECT foo
         , count(*) OVER() AS full_count
    FROM   bar
    WHERE  <some condition>
    ORDER  BY <some col>
    LIMIT  <pagesize>
    OFFSET <offset>
    

    이것은 총 카운트가없는 경우보다 상당히 비쌉니다. 모든 행을 계산해야하며 일치하는 색인에서 맨 위 행만 가져 오는 가능한 바로 가기는 더 이상 도움이되지 않을 수 있습니다. 작은 테이블이나 full_count <= OFFSET + LIMIT에서는 별 문제가되지 않습니다. 실질적으로 더 큰 full_count에 대한 사항.

    Corner case : OFFSET이 적어도 기본 쿼리의 행 수만큼 크면 행이 반환되지 않습니다. 따라서 full_count도 얻지 못합니다. 가능한 대안 :

    다음과 같은 일련의 이벤트를 고려하십시오.

    LIMIT / OFFSET은 테이블의 행 수가 증가함에 따라 점차 비효율적으로 변합니다. 더 나은 성능이 필요한 경우 대체 방법을 고려하십시오.

    영향을받는 행 수를 얻기위한 완전히 다른 접근 방식이 있습니다 (OFFSET & LIMIT가 적용되기 전에 전체 개수가 아님). Postgres는 마지막 SQL 명령의 영향을받은 행을 몇 개나 내부 부기를 가지고 있습니다. 일부 클라이언트는 해당 정보에 액세스하거나 psql과 같은 행 자체를 계산할 수 있습니다.

    예를 들어 plpgsql에서 영향을받은 행 수를 검색하려면 다음을 사용하여 SQL 명령을 실행 한 직후에 검색하십시오.

    GET DIAGNOSTICS integer_var = ROW_COUNT;
    

    매뉴얼의 세부 사항.

    또는 PHP에서 pg_num_rows를 사용할 수 있습니다. 또는 다른 클라이언트의 유사한 기능.

    관련 항목 :

  2. ==============================

    2.블로그에서 설명하는 것처럼 MySQL에는 SQL_CALC_FOUND_ROWS라는 기능이 있습니다. 이렇게하면 쿼리를 두 번 수행 할 필요가 없지만 제한 절이 조기에 중지하더라도 쿼리를 전체적으로 수행해야합니다.

    블로그에서 설명하는 것처럼 MySQL에는 SQL_CALC_FOUND_ROWS라는 기능이 있습니다. 이렇게하면 쿼리를 두 번 수행 할 필요가 없지만 제한 절이 조기에 중지하더라도 쿼리를 전체적으로 수행해야합니다.

    지금까지 내가 아는 한, PostgreSQL에는 비슷한 기능이 없습니다. 페이지 매기기 수행시주의해야 할 사항 (LIMIT이 IMHO로 사용되는 가장 일반적인 작업) : "OFFSET 1000 LIMIT 10"을 수행하면 DB에 1010 개 행을 가져와야한다는 의미입니다. 더 나은 수행 방법은 이전 행 (이 경우 1000 번째)에 대해 정렬하는 행의 값을 기억하고 "... WHERE order_row> value_of_1000_th LIMIT 10"과 같은 쿼리를 다시 작성하는 것입니다. 이점은 "order_row"가 대부분 인덱싱된다는 것입니다 (그렇지 않은 경우 문제가 발생 함). 단점은 새로운 요소가 페이지 뷰 사이에 추가되면 동기화가 다소 벗어날 수 있다는 것입니다 (하지만 다시 방문자가 관찰 할 수 없으며 성능이 크게 향상 될 수 있음).

  3. ==============================

    3.매번 COUNT () 쿼리를 실행하지 않아도 성능 저하를 줄일 수 있습니다. 쿼리를 다시 실행하기 전에 페이지 수를 캐시하십시오 (예 : 5 분). 엄청난 수의 INSERT를보고 있지 않다면 정상적으로 작동 할 것입니다.

    매번 COUNT () 쿼리를 실행하지 않아도 성능 저하를 줄일 수 있습니다. 쿼리를 다시 실행하기 전에 페이지 수를 캐시하십시오 (예 : 5 분). 엄청난 수의 INSERT를보고 있지 않다면 정상적으로 작동 할 것입니다.

  4. ==============================

    4.Postgres는 이미 일정량의 캐싱 작업을 수행하기 때문에 이러한 유형의 메소드는 비효율적이지 않습니다. 실행 시간이 두 배로 늘어나는 것은 아닙니다. DB 레이어에 타이머가 내장되어 있으므로 증거를 보았습니다.

    Postgres는 이미 일정량의 캐싱 작업을 수행하기 때문에 이러한 유형의 메소드는 비효율적이지 않습니다. 실행 시간이 두 배로 늘어나는 것은 아닙니다. DB 레이어에 타이머가 내장되어 있으므로 증거를 보았습니다.

  5. ==============================

    5.페이징의 목적을 알아야 할 필요가 있음을 알기 때문에 전체 쿼리를 한 번 실행하여 디스크에 서버 측 캐시로 데이터를 쓰고 페이징 메커니즘을 통해 데이터를 제공하는 것이 좋습니다.

    페이징의 목적을 알아야 할 필요가 있음을 알기 때문에 전체 쿼리를 한 번 실행하여 디스크에 서버 측 캐시로 데이터를 쓰고 페이징 메커니즘을 통해 데이터를 제공하는 것이 좋습니다.

    사용자에게 데이터를 제공할지 여부를 결정하기 위해 COUNT 검색어를 실행하는 경우 (즉, X 레코드가있는 경우 오류를 다시 표시) COUNT 접근 방식을 고수해야합니다.

  6. from https://stackoverflow.com/questions/156114/best-way-to-get-result-count-before-limit-was-applied by cc-by-sa and MIT license