본문 바로가기

빅데이터과정/SQL TUNING

#32_140728_TUNING_옵티마이져 연산자

728x90

# 옵티마이져 연산자






data를 엑세스 하는 방법
 



  • FULL TABLE SCAN



full table scan (힌트 : /*+ full(테이블명) */ )

1.     high water mark까지 스캔하는 방법

2.     full table scan이 유리한 이유
테이블에서 엑세스 하고자 하는 데이터가 많을 때

3.     full table scan을 할 수 밖에 없는 경우
1)     인덱스가 없을 때
2)     테이블의 통계정보를 수집할 때
3)     인덱스를 생성할 때
4)     full 힌트를 생성할 때


full table scan을 빠르게 하는 방법 2가지

1.     full table scan에 관련된 오라클 파라미터의 값을 조정한다
db_file_multiblock_read_count : 이 파라미터는 full table scan을 할 때 한번에 읽어들이는 블록의 개수를 결정

2.     병렬로 작업한다 힌트사용(/*+ parallel(emp,4) */)


파라미터를 조절하여 full table scan 속도 테스트

1.     SQL> set timing on

2.     SQL> create table sales300
   as
   select * from sh.sales;

3.     SQL> insert into sales300
   select * from sh.sales;

4.     SQL> insert into sales300
   select * from sales300;

5.     SQL> commit;

6.     SQL> alter session set db_file_multiblock_read_count=16;

7.     SQL> create table sales400
as select * from sales300;

8.     SQL> @flush.sql

9.     SQL> drop table sales400 purge;

10.   SQL> connect scott/tiger

11.   SQL> alter session set db_file_multiblock_read_count=128;

12.   SQL> set timing on

13.   SQL> create table sales400
as select * from sales300;

SQL> connect /as sysdba
SQL> alter session set db_file_multiblock_read_count=16;
SQL> connect scott/tiger
SQL> create table sales400
as select * from sales300;
Elapsed: 00:00:54.73
SQL> @flush.sql
SQL> drop table sales400 purge;
SQL> connect scott/tiger
SQL>alter session set db_file_multiblock_read_count=128;
SQL> create table sales400
as select * from sales300;
Elapsed: 00:00:49.83
위의 수행결과를 보면 db_file_multiblock_read_count을 수행하면 속도가 빨라진 것을 확인 할 수 있다



  • ROWID SCAN


rowid에 의한 스캔 (힌트 : /*+ rowid(테이블명) */ )
rowid : 해당 row의 물리적 주소(file# + block# + row#)

SQL> SQL> select rowid, empno, ename sal from emp;
ROWID                   EMPNO SAL
------------------ ---------- ----------
AAAVl7AAFAAAAG7AAA       7839 KING
AAAVl7AAFAAAAG7AAB       7698 BLAKE
………………………………………………….

rowid에 의한 스캔은 하나의 로우를 스캔하는 가장 빠른 방법이다

인덱스의 구조
컬럼값 + rowid
컬럼값은 데이터가 ascending으로 저장되어있다.
 : SQL> select ename, rowid
       from emp
       where ename > ‘   ‘;
SQL> SQL> select rowid, empno, ename sal from emp;
ROWID                   EMPNO SAL
------------------ ---------- ----------
AAAVl7AAFAAAAG7AAA       7839 KING
AAAVl7AAFAAAAG7AAB       7698 BLAKE
AAAVl7AAFAAAAG7AAC       7782 CLARK
AAAVl7AAFAAAAG7AAD       7566 JONES
AAAVl7AAFAAAAG7AAE       7654 MARTIN
………………………………………………



문제8. 사원 테이블에서 이름에 EN 또는 IN을 포함하고 있는 사원들의 이름과 월급과 직업을 출력하시오

CREATE INDEX emp_ename ON EMP(ename);

SELECT ename, sal, job
FROM EMP
WHERE ename like '%EN%' OR ename LIKE '%IN%';

index 를 만들어줬지만 수행결과 full table scan을 하는 것을 확인할 수 있다결국 위의 쿼리는 악성 SQL이다




문제10. 이름이 EN 또는 IN을 포함하고 있는 사원들의 rowid 만 출력하는 쿼리가 아래와 같은데 이 쿼리를 rowid를 이용해서 사원의 이름과 월급과 직업을 출력하는 쿼리를 다시 작성하시오

SELECT ROWID
FROM EMP
WHERE ename like '%EN%' OR ename LIKE '%IN%';

  
SELECT ename, job, sal
FROM EMP
WHERE ROWID IN ('AAAVl7AAFAAAAG7AAF', 'AAAVl7AAFAAAAG7AAA', 'AAAVl7AAFAAAAG7AAE');
SELECT ename, job, sal
FROM EMP
WHERE ROWID IN
알아낸 rowid로 스캔
 (SELECT ROWID FROM EMP
 WHERE ename like '%EN%' OR ename LIKE '%IN%');
인덱스만 scan해서 rowid 조회




변형기가 아래와 같이 쿼리를 변경했기 때문에 위의 쿼리가 full table scan을 확인할 수 있다
SELECT ename, sal, job FROM EMP WHERE ename like '%EN%' OR ename LIKE '%IN%';

SELECT ename, job, sal
FROM EMP
WHERE ROWID IN
 (SELECT /*+ no_query_transformation */ ROWID FROM EMP
 WHERE ename like '%EN%' OR ename LIKE '%IN%');

no_query_transformation 힌트를 이용하면 변형기가 변경하여 수행하는 것을 막을 수 있고 속도를 빠르게 할 수 있다
위의 수행결과를 최종적으로 조인으로 변경해야 한다
여기서 filter 수행의 의미는 메인 쿼리를 수행했다는 것이다.



  • 샘플 테이블 스캔


SQL> SELECT COUNT(*) FROM sales100;
  COUNT(*)
----------
    918843
SQL> SELECT COUNT(*) FROM sales100 SAMPLE BLOCK(10);
  COUNT(*)
----------
     52623
sample block(10)은 조회된 데이터의 10%만 조회하겠다는 의미이다





  • B-TREE INDEX





문제11. 아래의 SQL을 수행하여 sales500 테이블을 생성하고 sales500의 SQL 속도를 높이기 위해서RN 컬럼의 인덱스를 생성하고 아래의 퀴리를 조회하시오(sales500는  7350744개의 데이터가 들어있는 테이블이다)
SQL> create table sales400
as
select * from sh.sales;
SQL> INSERT INTO sales400
 SELECT * FROM sales400;
SQL> INSERT INTO sales400
 SELECT * FROM sales400;
SQL> DROP TABLE sales500 purge;
SQL> CREATE  TABLE sales500
AS
SELECT  ROWNUM  AS rn , sales400.*,
 ROUND(DBMS_RANDOM.VALUE *1000) AS  profit
 FROM sales400;

#쿼리 조회
SQL> SELECT * FROM sales500
WHERE rn = 2929153;

튜닝 전

SELECT * FROM sales500
WHERE rn = 2929153;
이 쿼리를 수행하면 6초가 걸린다
결국 위 쿼리는 아래의 쿼리와 같다
SELECT select /*+ full(sales500) */ *
FROM sales500
WHERE rn = 2929153;

튜닝 후

alter session set db_file_multiblock_read_count=128;
alter session set workarea_size_policy = manual;
alter session set sort_area_size=1000000000;
CREATE INDEX sales500_rn ON sales500(rn);

SELECT * FROM sales500
WHERE rn = 2929153;
위 설정을 수행한 후 조회하면 1초도 안걸리는 것을 확인할 수 있다
위 과정은 아래의 쿼리와 같다
SELECT /* index(sales500 sales500_rn) */ * FROM sales500
WHERE rn = 2929153;







SQL gate에서 자동 추적

튜닝을 위해서는 시간과 블록정보를 비교할 수 있는데 정확한 것은 블록정보를 가지고 비교하는 것이다
왜냐하면 DB의 부하정도에 따라서 걸리는 시간은 달라질 수 있기 때문이다


1.     index table scan

SQL> SELECT /*+ index(sales500, sales500_rn) */ * FROM sales500
WHERE rn = 2929153;




db block gets        0
메모리에서 읽은 버퍼의 개수
consistent gets       45
메모리에서 읽은 버퍼의 개수
physical reads        0
디스크에서 읽은 블록의 개수



2.     full table scan

SELECT /*+ full(sales500) */ *
FROM sales500
WHERE rn = 2929153;





문제12. 아래의 SQL의 튜닝전후를 통계지표로 비교하시오

select /* full(emp) */ ename, sal, job from emp
where sal = 3000;
db block gets        0
consistent gets       62
physical reads        0
select /*+ index(emp, emp_sal) */ ename, sal, job from emp
where sal = 3000;
db block gets        0
consistent gets       61
physical reads        0



'빅데이터과정 > SQL TUNING' 카테고리의 다른 글

#34_140730_TUNING_SORTING OPERATION  (0) 2014.07.30
#34_140730_TUNING_INVISIBLE INDEX  (0) 2014.07.30
#33_140729_TUNING_INDEX MONITORING  (0) 2014.07.29
#33_140729_TUNING_INDEX SCAN  (0) 2014.07.29
#32_140728_TUNING_TUNING BASIC  (0) 2014.07.28