로우 랜덤 조회

2021. 12. 24.·Oracle/Performance

개요

랜덤 Ton-N 쿼리를 사용하지 않아도 로우를 랜덤하게 조회할 수 있습니다.

 

테스트를 위해 아래와 같이 테이블을 생성하겠습니다. t1 테이블에는 10,000,000개의 행이 저장되어 있습니다.

-- 1
DROP TABLE t1 PURGE;
DROP TABLE t2 PURGE;
DROP TABLE t3 PURGE;
DROP TABLE t4 PURGE;

CREATE TABLE t1 (c1, c2) AS SELECT ROWNUM, LPAD ('X', 100, 'X') FROM XMLTABLE ('1 to 10000000');
CREATE TABLE t2 (c1 NUMBER, c2 VARCHAR2(100));
CREATE TABLE t3 (c1 NUMBER, c2 VARCHAR2(100));
CREATE TABLE t4 (c1 NUMBER, c2 VARCHAR2(100));

CREATE UNIQUE INDEX t1_u1 ON t1 (c1);

 

SAMPLE 절

아래 쿼리는 SAMPLE 절로 로우를 랜덤하게 조회합니다. 3개의 블록 I/O가 발생합니다.

-- 2
SELECT c1
  FROM t1 SAMPLE (1)
 WHERE ROWNUM = 1;

--------------------------------------------------------
| Id  | Operation            | Name | A-Rows | Buffers |
--------------------------------------------------------
|   0 | SELECT STATEMENT     |      |      1 |       3 |
|*  1 |  COUNT STOPKEY       |      |      1 |       3 |
|   2 |   TABLE ACCESS SAMPLE| T1   |      1 |       3 |
--------------------------------------------------------

 

데이터 분포를 확인하기 위해 앞선 쿼리를 10,000번 수행한 결과를 t2 테이블에 저장하겠습니다. 수행에 7.58초가 소요됩니다.

-- 3
BEGIN
    FOR i IN 1 .. 10000 LOOP
        INSERT
          INTO t2
        SELECT *
          FROM t1 SAMPLE (1)
         WHERE ROWNUM = 1;
    END LOOP;

    COMMIT;
END;
/

경   과: 00:00:07.58

 

t2 테이블의 백분위 비율을 조회하면 대부분의 데이터가 1에서 100,000 사이에 분포되어 있음을 알 수 있습니다.

-- 4
SELECT   CEIL (c1 / 100000) AS c1
       , COUNT (*) AS cnt
    FROM t2
GROUP BY CEIL (c1 / 100000)
ORDER BY c1;

C1   CNT
-- -----
 1 10000

1개의 행이 선택되었습니다.

 

SAMPLE BLOCK 절

아래 쿼리는 SAMPLE BLOCK 절로 로우를 랜덤하게 조회합니다. 13개의 블록 I/O가 발생합니다.

-- 5
SELECT c1
  FROM t1 SAMPLE BLOCK (1)
 WHERE ROWNUM = 1;

--------------------------------------------------------
| Id  | Operation            | Name | A-Rows | Buffers |
--------------------------------------------------------
|   0 | SELECT STATEMENT     |      |      1 |      13 |
|*  1 |  COUNT STOPKEY       |      |      1 |      13 |
|   2 |   TABLE ACCESS SAMPLE| T1   |      1 |      13 |
--------------------------------------------------------

 

데이터 분포를 확인하기 위해 앞선 쿼리를 10,000번 수행한 결과를 t3 테이블에 저장하겠습니다. 수행에 10.28초가 소요됩니다.

-- 6
TRUNCATE TABLE t2;

BEGIN
    FOR i IN 1 .. 10000 LOOP
        INSERT
          INTO t2
        SELECT *
          FROM t1 SAMPLE BLOCK (1)
         WHERE ROWNUM = 1;
    END LOOP;

    COMMIT;
END;
/

PL/SQL 처리가 정상적으로 완료되었습니다.

경   과: 00:00:10.28

 

t3 테이블의 백분위 비율을 조회하면 SAMPLE 절에 비해 데이터 분포가 넓지만 대부분의 데이터가 1에서 5,000,000 사이에 분포되어 있음을 알 수 있습니다.

-- 7
SELECT   CEIL (c1 / 100000) AS c1
       , COUNT (*) AS cnt
    FROM t2
GROUP BY CEIL (c1 / 100000)
ORDER BY c1;

C1  CNT
-- ----
 1 1088
 2 1076
...
46    9
56    8

42 행이 선택되었습니다.

 

DBMS_RANDOM.VALUE 함수

PK가 순번이면 DBMS_RANDOM.VALUE 함수로 키 값을 생성할 수 있습니다. 아래 쿼리는 DBMS_RANDOM.VALUE 함수로 로우를 랜덤하게 조회합니다. 4개의 블록 I/O가 발생합니다.

-- 8
SELECT *
  FROM t1
 WHERE c1 = CEIL (DBMS_RANDOM.VALUE (1, 10000000));

----------------------------------------------------------------
| Id  | Operation                   | Name  | A-Rows | Buffers |
----------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |      1 |       4 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1    |      1 |       4 |
|*  2 |   INDEX UNIQUE SCAN         | T1_U1 |      1 |       3 |
----------------------------------------------------------------

 

데이터 분포를 확인하기 위해 앞선 쿼리를 10,000번 수행한 결과를 t4 테이블에 저장하겠습니다. 수행에 3.08초가 소요됩니다.

-- 9
TRUNCATE TABLE t2;

BEGIN
    FOR i IN 1 .. 10000 LOOP
        INSERT
          INTO t2
        SELECT *
          FROM t1
         WHERE c1 = CEIL (DBMS_RANDOM.VALUE (1, 10000000));
    END LOOP;

    COMMIT;
END;
/

PL/SQL 처리가 정상적으로 완료되었습니다.

경   과: 00:00:03.08

 

t4 테이블의 백분위 비율을 조회하면 데이터 분포가 균등한 것을 확인할 수 있습니다.

-- 10
SELECT   CEIL (c1 / 100000) AS c1
       , COUNT (*) AS cnt
    FROM t2
GROUP BY CEIL (c1 / 100000)
ORDER BY c1;

 C1 CNT
--- ---
  1  95
  2  98
...
 99 106
100 113

100 행이 선택되었습니다.

 

결과

아래 표는 앞서 테스트한 결과를 보여줍니다.

방식 블록 I/O 수행시간 (10,000번) 데이터 분포
SAMPLE 절 3 7.58 매우 나쁨
SAMPLE BLOCK 절 13 10.28 나쁨
DBMS_RANDOM.VALUE 함수 4 3.08 매우 좋음

 

관련 링크

  • hrjeong.tistory.com - 랜덤 Top-N 쿼리
저작자표시 비영리 변경금지 (새창열림)
'Oracle/Performance' 카테고리의 다른 글
  • OR 조인 조건을 사용한 아우터 조인의 성능 저하 #1
  • Historical SQL Monitor Report
  • 병렬 쿼리에서 사용자 정의 함수의 동작 #2
  • 병렬 쿼리에서 사용자 정의 함수의 동작 #1
정희락
정희락
2007년부터 Oracle Database 성능 최적화에 관심을 가져왔습니다. 현재 한국오라클 Engineered Systems Solution Engineering 팀에서 Solution Engineer로 근무하고 있습니다. 이 블로그는 개인적인 연구 목적으로 운영되며 Oracle 사의 공식적인 입장을 대변하지 않습니다.
  • 정희락
    TunA
    정희락
  • 전체
    오늘
    어제
    • 분류 전체보기 (201)
      • Oracle (173)
        • SQL (33)
        • PLSQL (10)
        • Performance (74)
        • Administration (37)
        • Installation (3)
        • Utilities (1)
        • JSON (8)
        • Vector (7)
      • Exadata (15)
      • SQL*Plus (2)
      • Linux (5)
      • Resources (6)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 도서

    • 불친절한 SQL 프로그래밍
    • 불친절한 PL/SQL 프로그래밍
  • 링크

    • Connor McDonald
    • Frits Hoogland
    • Jonathan Lewis
    • Julian Dontcheff
    • Julian Dyke
    • Kun Sun
    • Maria Colgan
    • Martin Bach
    • Mike Dietrich
    • Tanel Poder
  • 공지사항

  • 인기 글

  • 태그

    12c
    19c
    21c
    23ai
    case study
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
정희락
로우 랜덤 조회
상단으로

티스토리툴바