저는 제가 원하는만큼 Oracle에 익숙하지 않습니다. 약 25 만 개의 레코드가 있으며 페이지 당 100 개를 표시하고 싶습니다. 현재 데이터 어댑터 및 데이터 세트를 사용하여 데이터 세트에 25 만 개의 레코드를 모두 검색하는 하나의 저장 프로 시저와 저장된 프로 시저의 결과에 대한 dataadapter.Fill (dataset) 메서드가 있습니다. 매개 변수로 전달할 수있는 정수 값으로 “페이지 번호”및 “페이지 당 레코드 수”가있는 경우 해당 특정 섹션 만 되 돌리는 가장 좋은 방법은 무엇일까요? 내가 페이지 번호로 10을 전달하고 페이지 수로 120을 전달하면 select 문에서 1880 번째에서 1200 번째까지를 줄 것입니다.
나는 C #으로 .NET에서 이것을하고 있는데, 그것이 중요하지 않다고 생각했다. 내가 SQL 측에서 바로 얻을 수 있다면 나는 멋지다.
업데이트 : Brian의 제안을 사용할 수 있었고 잘 작동합니다. 몇 가지 최적화 작업을하고 싶지만 페이지가 1 분이 아닌 4 ~ 5 초 내에 표시되고 내 페이징 제어가 새 저장된 프록과 매우 잘 통합 될 수있었습니다.
답변
이와 같은 것이 작동합니다. From Frans Bouma의 블로그
SELECT * FROM
(
SELECT a.*, rownum r__
FROM
(
SELECT * FROM ORDERS WHERE CustomerID LIKE 'A%'
ORDER BY OrderDate DESC, ShippingDate DESC
) a
WHERE rownum < ((pageNumber * pageSize) + 1 )
)
WHERE r__ >= (((pageNumber-1) * pageSize) + 1)
답변
페이지 매김과 매우 유용한 분석 기능에 대해 Tom에게 물어보십시오 .
다음은 해당 페이지에서 발췌 한 것입니다.
select * from (
select /*+ first_rows(25) */
object_id,object_name,
row_number() over
(order by object_id) rn
from all_objects)
where rn between :n and :m
order by rn;
답변
완성도 를 높이기 위해 더 현대적인 솔루션을 찾는 사람들을 위해 Oracle 12c 에는 더 나은 페이징 및 상위 처리를 포함한 몇 가지 새로운 기능이 있습니다.
페이징
페이징은 다음과 같습니다.
SELECT *
FROM user
ORDER BY first_name
OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY;
상위 N 개 기록
최고 기록을 얻는 것은 다음과 같습니다.
SELECT *
FROM user
ORDER BY first_name
FETCH FIRST 5 ROWS ONLY
위의 두 쿼리 예제에 어떻게 ORDER BY
절이 있는지 확인하십시오 . 새 명령은이를 존중하고 정렬 된 데이터에서 실행됩니다.
FETCH
또는에 대한 좋은 Oracle 참조 페이지를 찾을 수 OFFSET
없었지만 이 페이지 에는 이러한 새로운 기능에 대한 훌륭한 개요가 있습니다.
공연
@wweicker가 아래 주석에서 지적했듯이 성능은 12c의 새로운 구문에서 문제입니다. Oracle이 이후 개선했는지 테스트 할 18c 사본이 없었습니다.
흥미롭게도 새 메서드에 대해 테이블 (1 억 1,300 만 개 이상의 행)에 대한 쿼리를 처음 실행했을 때 실제 결과가 약간 더 빨리 반환되었습니다.
- 새로운 방법 : 0.013 초.
- 이전 방법 : 0.107 초.
그러나 @wweicker가 언급했듯이 설명 계획은 새로운 방법에 대해 훨씬 더 나빠 보입니다.
- 새로운 방법 비용 : 300,110
- 기존 방법 비용 : 30
새로운 구문은 전체 비용이었던 내 열의 인덱스 전체를 스캔했습니다. 인덱싱되지 않은 데이터를 제한하면 상황이 훨씬 더 악화 될 가능성이 있습니다.
이전 데이터 세트에 인덱싱되지 않은 단일 열을 포함하는 경우를 살펴 보겠습니다.
- 새로운 방법 시간 / 비용 : 189.55 초 / 998,908
- 기존 방법 시간 / 비용 : 1.973 초 / 256
요약 : Oracle이이 처리를 개선 할 때까지주의해서 사용하십시오. 작업 할 색인이있는 경우 새 방법을 사용하지 않아도됩니다.
조만간 사용할 18c 사본을 갖고 업데이트 할 수 있기를 바랍니다.
답변
답변과 의견을 요약하고 싶습니다. 페이지 매김을 수행하는 방법에는 여러 가지가 있습니다.
Oracle 12c 이전에는 OFFSET / FETCH 기능이 없었으므로 @jasonk가 제안한 백서 를 살펴보십시오 . 장단점에 대한 자세한 설명과 함께 다양한 방법에 대해 찾은 가장 완벽한 기사입니다. 여기에 복사하여 붙여 넣는 데 상당한 시간이 걸리므로하지 않습니다.
오라클 및 기타 데이터베이스 페이지 매김에 대한 몇 가지 일반적인주의 사항을 설명하는 jooq 제작자의 좋은 기사도 있습니다. jooq의 블로그 포스트
좋은 소식입니다. Oracle 12c 이후로 새로운 OFFSET / FETCH 기능이 있습니다. OracleMagazine 12c의 새로운 기능 . “Top-N 쿼리 및 페이지 매김”을 참조하십시오.
다음 진술을 발행하여 Oracle 버전을 확인할 수 있습니다.
SELECT * FROM V$VERSION
답변
다음을 시도하십시오.
SELECT *
FROM
(SELECT FIELDA,
FIELDB,
FIELDC,
ROW_NUMBER() OVER (ORDER BY FIELDC) R
FROM TABLE_NAME
WHERE FIELDA = 10
)
WHERE R >= 10
AND R <= 15;
[tecnicume]을 통해
답변
내 프로젝트에서는 Oracle 12c 및 java를 사용했습니다 . 페이징 코드는 다음과 같습니다.
public public List<Map<String, Object>> getAllProductOfferWithPagination(int pageNo, int pageElementSize, Long productOfferId, String productOfferName) {
try {
if(pageNo==1){
//do nothing
} else{
pageNo=(pageNo-1)*pageElementSize+1;
}
System.out.println("algo pageNo: " + pageNo +" pageElementSize: "+ pageElementSize+" productOfferId: "+ productOfferId+" productOfferName: "+ productOfferName);
String sql = "SELECT * FROM ( SELECT * FROM product_offer po WHERE po.deleted=0 AND (po.product_offer_id=? OR po.product_offer_name LIKE ? )" +
" ORDER BY po.PRODUCT_OFFER_ID asc) foo OFFSET ? ROWS FETCH NEXT ? ROWS ONLY ";
return jdbcTemplate.queryForList(sql,new Object[] {productOfferId,"%"+productOfferName+"%",pageNo-1, pageElementSize});
} catch (Exception e) {
System.out.println(e);
e.printStackTrace();
return null;
}