복붙노트

[SQL] LIMIT이 적용되기 전에 가장 좋은 방법은 결과 수를 얻을 수 있습니다

SQL

LIMIT이 적용되기 전에 가장 좋은 방법은 결과 수를 얻을 수 있습니다

DB를에서 오는 데이터를 페이징하면 페이지 점프 컨트롤을 렌더링 할 수있을 것입니다 얼마나 많은 페이지를 알아야합니다.

현재 내가 두 번, 한 번에 전체 결과를 결정하는 계수 ()에 싸여 쿼리를 실행하여 그렇게하고, 한계와 두 번 다시 나는 현재 페이지에 필요한 바로 결과를 얻을 적용했다.

이것은 비효율적 인 것 같다. LIMIT이 적용되기 전에 반환 된 얼마나 많은 결과를 결정하는 더 좋은 방법이 있나요?

나는 PHP와 포스트 그레스를 사용하고 있습니다.

해결법

  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와 <=가 + LIMIT를 OFFSET하지 않습니다. 실질적으로 더 큰 full_count에 대한 사항.

    코너의 경우 : OFFSET은 기본 쿼리에서 행의 수와 같은 큰대로 적어도 때, 어떤 행이 반환되지 않습니다. 그래서 당신은 또한 더 full_count를 얻을 수 없습니다. 가능한 대안 :

    (0 CTE를 평가하고 구체화 별도.에서 포스트 그레스 12 이상 플래너 직장에 가기 전에 하위 쿼리와 같은 사람들을 인라인 수 있습니다.) 여기가 아님.

    (2. GROUP BY 및 집계 함수는 여기에 갈 것입니다.) 여기가 아님.

    (3. 기타 SELECT리스트 표현식은 그룹화 / 집계 열을 기반으로, 평가됩니다.) 여기가 아님.

    (6. DISTINCT 또는 DISTINCT ON 여기에 갈 것입니다.) 여기가 아님.

    LIMIT는 / OFFSET은 테이블의 행의 수가 증가하고 점점 비효율적이된다. 당신이 더 나은 성능을 필요로하는 경우 다른 방법을 고려 :

    영향을받는 행의 수 (OFFSET 및 LIMIT이 적용되기 전에 아니라 풀 카운트)를 얻기 위해 완전히 다른 접근 방법이있다. 포스트 그레스는 마지막 SQL 명령에 의해 영향을받는 행 수를 내부 부기가 있습니다. 일부 클라이언트는이 정보에 액세스하거나 (psql를 같은) 행 자체를 셀 수 있습니다.

    예를 들어, 당신은 즉시로 SQL 명령을 실행 한 후 plpgsql에 영향을받는 행의 수를 검색 할 수 있습니다 :

    GET DIAGNOSTICS integer_var = ROW_COUNT;
    

    매뉴얼의 세부 사항.

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

    관련 :

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

    2.내 블로그에 설명 된 바와 같이, MySQL은 SQL_CALC_FOUND_ROWS라는 기능이 있습니다. 이 두 번 쿼리를 수행 할 필요성을 제거하지만 여전히 제한 조항이 일찍 중단 할 수했을 경우에도, 그 entireity에 쿼리를 할 필요가있다.

    내 블로그에 설명 된 바와 같이, MySQL은 SQL_CALC_FOUND_ROWS라는 기능이 있습니다. 이 두 번 쿼리를 수행 할 필요성을 제거하지만 여전히 제한 조항이 일찍 중단 할 수했을 경우에도, 그 entireity에 쿼리를 할 필요가있다.

    지금까지 내가 아는 한, PostgreSQL을위한 유사한 기능이 없습니다. 하고 AN, DB를 적어도 1010 개 행을 인출한다는 것을 의미한다 "1000 LIMIT 10 OFFSET"그것은 단지 당신에게 (10)을 제공하는 경우에도 : 매김을 할 때 조심하는 것은 (가장 일반적인 것은있는 LIMIT는 사용 IMHO입니다). 할 수있는 더 성능이 좋은 방법은 당신이 이전 행 (이 경우 1000)에 의해 주문하는 행의 값을 기억하고이 같은 쿼리를 다시 작성하는 것입니다 : "... WHERE order_row> value_of_1000_th LIMIT 10". (아니, 당신은 문제를 이동 한 경우) 장점은 "order_row는"대부분의 아마 색인이 있다는 점이다. 새로운 요소가 페이지 뷰 사이에 추가하는 경우,이 동기화에서 조금 얻을 수있는 단점은 (그러나 다시, 그것은 방문자에 의해 관찰하지 않을 수와 큰 성능을 얻을 수 있습니다).

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

    3.당신은 때마다 COUNT () 쿼리를 실행하지 않음으로써 성능 저하를 완화 할 수있다. , 페이지 수를 캐시 쿼리를 다시 실행 오분 전에 말한다. 당신 인서트의 거대한 숫자를보고하지 않는 한, 그건 그냥 잘 작동합니다.

    당신은 때마다 COUNT () 쿼리를 실행하지 않음으로써 성능 저하를 완화 할 수있다. , 페이지 수를 캐시 쿼리를 다시 실행 오분 전에 말한다. 당신 인서트의 거대한 숫자를보고하지 않는 한, 그건 그냥 잘 작동합니다.

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

    4.포스트 그레스는 이미 일을 캐싱의 일정 금액을 수행하기 때문에, 방법의이 유형은 보이는만큼 비효율적 없습니다. 확실히 실행 시간을 두 배로 아닙니다. 내가 증거를 보았다 그래서 우리는 우리의 DB 층에 내장 된 타이머가있다.

    포스트 그레스는 이미 일을 캐싱의 일정 금액을 수행하기 때문에, 방법의이 유형은 보이는만큼 비효율적 없습니다. 확실히 실행 시간을 두 배로 아닙니다. 내가 증거를 보았다 그래서 우리는 우리의 DB 층에 내장 된 타이머가있다.

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

    5.당신이 페이징의 목적을 위해 알아야 할, 나는이 한 번 전체 쿼리를 실행하는 서버 측 캐시로 디스크에 데이터를 기록, 다음 페이징 메커니즘을 통해 것을 공급 좋을 것보고.

    당신이 페이징의 목적을 위해 알아야 할, 나는이 한 번 전체 쿼리를 실행하는 서버 측 캐시로 디스크에 데이터를 기록, 다음 페이징 메커니즘을 통해 것을 공급 좋을 것보고.

    당신이 (> X 레코드가있는 경우 즉, 오류를 다시 제공) 사용자에게 데이터를 제공할지 여부를 결정하기위한 목적으로 COUNT 쿼리를 실행하는 경우, 당신은 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