날아라쩡글이의 블로그입니다.
VIEW,인덱스, 서브쿼리 본문
728x90
반응형
뷰 (VIEW)
- 테이블 혹은 다른 뷰를 기반으로 하는 가상의 테이블 (논리적인 테이블) 이다.
- 특징
- 물리적인 저장공간을 가지지 않는다.
- 애초에 존재하지 않는다.
- INSERT, UPDATE, DELETE 작업의 수행이 불편하다.
- 직원에 대한 상세정보가 적힌 가상의 테이블로써 제약조건이 존재하지 않고, 모델도 따로 존재하지 않는다. 실제하지 않는 테이블이라는 뜻이다.
- 물리적인 저장공간을 가지지 않는다.
- 목적
- 복잡한 SQL문을 간단하게 작성하기 위해서 사용한다.
- 데이터의 엑세스를 제한하기 위해서 사용한다.(데이터에 대한 보안성 강화)
- 사용자의 권한과 연관이 있다.
- 동일한 데이터로부터 다양한 결과를 얻기위해서 사용한다.
뷰 정의 하기 (가상의 테이블)
- CREATE OR REPLACE VIEW EMP_SALARY_DETAIL_VIEW
AS
SELECT E.EMPLOYEE_ID, E.FIRST_NAME, E.JOB_ID, E.DEPARTMENT_ID, D.DEPARTMENT_NAME, E.COMMISSION_PCT, S.GRADE,
E.SALARY*12+E.SALARY*NVL(COMMISSION_PCT, 0)*12 ANNUAL_SALARY
FROM EMPLOYEES E, DEPARTMENTS D , SALARY_GRADE S
WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID
AND E.SALARY >= S.MIN_SALARY AND E.SALARY <= S.MAX_SALARY
WITH READ ONLY;
- CREATE OR REPLACE VIEW를 이용하여 VIEW를 덮어쓸 수 있다.
- WITH READ ONLY
- 읽기만 가능하다는 뜻이다.
- AS 이후에는 서브쿼리로 SELECT를 입력했다.
- 서브쿼리 : SQL을 가상의 테이블이 포장한 데이터를 조회하는 SELECT문이다.
- 전체사원의 쿼리는 SELECT의 실행결과로 언제나 TABLE의 형태로 보일 수 있다.
- SELECT문은 곧 TABLE을 의미한다.
- 가상의 TABLE은 메모리에 존재하는 SELECT문의 실행결과를 의미한다.
- 이 결과를 저장하길 원한다.
- 쿼리 자체의 실행결과를 가상테이블로 보는 것이다.
- 쿼리실행결과를 가상의 테이블로 만들어 놓는다.
- 사용방법
- 뷰를 정의한다.
- SELECT *
FROM 뷰(가상의 테이블)명칭
WHERE 조건식; --> 방법으로 사용한다.- FROM 절에는 1. 테이블 이름, 2. VIEW이름을 사용할 수 있다.
- 테이블이름 : 테이블에서 가져온다.
- VIEW이름 : 쿼리의 결과를 가상의 테이블로 본다.
- 쿼리의 실행결과가 데이터에는 테이블처럼 보인다.
- 이전 진행방법 : 급여 등급별 인원수 조회하기
- SELECT S.GRADE, COUNT(*)
FROM EMPLOYEES E, SALARY_GRADE S
WHERE E.SALARY >= S.MIN_SALARY AND E.SALARY <= S.MAX_SALARY
GROUP BY S.GRADE;
- SELECT S.GRADE, COUNT(*)
- 뷰를 사용하여 진행하는 방법
- SELECT EMP_SALARY_GRADE, COUNT(*)
FROM EMP_DETAILS_VIEW
GROUP BY EMP_SALARY_GRADE; - 뷰의 별칭을 이용하여 간편하게 조회할 수 있다.
- SELECT EMP_SALARY_GRADE, COUNT(*)
- 사용목적의 복잡한 SQL문을 간단하게 작성하기 위해서 사용한를 충족한다.
- 뷰는 가상의 테이블의 형태를 가지기 때문에 다른 사람에게 보여주기 싫을 때 뷰로 데이터를 만들어서 보여줄 수 있다.
- 개발자들은 데이터의 전체적인 부분이나 업무, 업체에 대한 이해도가 낮을 수 있기 때문에 기업에서는 실제 테이블에 대한 접근을 허용하지 않을 수 있다.
- WEB PAGE에 필요한 가상의 테이블만 볼 수 있게 개발자에게 가상의 테이블만 전달할 수 있다.
- 가상의 테이블로 보여주면서
- 사용목적의 데이터의 엑세스를 제한하기 위해서 사용한다.(데이터에 대한 보안성 강화)을 충족시킬 수 있다.
- 쿼리중
- EMPLOYEES + DEPARTMENTS + SALARY_GRADE
- 직원의 급여, 연봉상세정보, 부서의 이름을 가상의 TABLE로 획득할 수 있다.
- EMPLOYEES + DEPARTMENTS + EMPLOYEES
- 셀프쿼리로 직원과 매니저의 상세정보를 획득할 수 있다.
- EMPLOYEES + DEPARTMENTS + JOBS
- 직원, 부서, 직종의 상세정보를 획득할 수 있다.
- 조인조건으로 다양한 결과가 출력된다.
- 사용목적 중 동일한 데이터로부터 다양한 결과를 얻기위해서 사용을 충족한다.
- 뷰를 사용하면 좀더 쉽고, 빠르고, 적은 코딩, 빠르고 간단한 명령어로 추적이 가능하다.
- EMPLOYEES + DEPARTMENTS + SALARY_GRADE
- 뷰의 종류
- 단순 뷰
- 한 테이블에서만 데이터를 가져온다.
- 함수 또는 데이터 그룹을 사용하지 않았음
- 테이블 1개에서만 사용한다.
- DML의 언어를 사용 가능은 하지 만, 대부분의 뷰는 WITH READ ONLY로 변경하여 사용한다.
- 복합 뷰
- 여러테이블에서 데이터를 가져온다.
- 함수 또는 데이터 그룹을 포함하고 있다.
- 뷰의 수정
- CREATE OR REPLACE VIEW NAME
AS 서브쿼리
로 생성하고, 만들면 된다. --> 생성도 덮어버리는 것이 좋다.
- CREATE OR REPLACE VIEW NAME
- 단순 뷰
- 인라인 뷰
- 쿼리 실행동안만 가상의 테이블이 생성이 되는 것이다. 쿼리실행이 종료시 삭제된다.
- SELECT 테이블1.컬럼 2, 테이블2.컬럼3
FROM (SELECT 컬럼1 FROM 테이블 1 WHERE 조건식 ) 테이블1, 테이블2
WHERE 조건식- 인라인 뷰 : FROM절에 씌이는 서브쿼리로 가상의 테이블로 볼 수 있으며, 원칙적으로 1회성으로 사용한다.
- 쿼리란 TABLE과 TABLE의 join이다. --> SELECT문의 결과를 활용하기 위해 권장되는 방법이다.
- SELECT문으로 가상의 테이블을 만들 수 있다.
- 페이징 처리
- 데이터를 화면에 표시할때, 화면의 표시양은 제한적이다.
- 무한 스크롤은 어렵기 때문에 PAGE의 번호를 붙여 10개 출력후 다음 10개출력 방법으로 나오게 만드는 방법
- 인라인 뷰를 많이 사용한다.
- TOP-N분석도 같은 방법이다.
- 특정컬럼을 오름차순과 내림차순으로 정렬후 1~3등의 사이를 알고싶을때 사용하는 방법이다.
위치에 따른 뷰의 이름
- SELECT
- 스칼라서브쿼리
- 단순값처럼 취급되는 서브쿼리이다.
- 스칼라서브쿼리
- FROM
- 인라인 뷰
- 뷰를 가상의 테이블로 만들어서 사용하는 서브쿼리이다.
- 인라인 뷰
- WHERE
- 서브쿼리
- 조건식의 값으로 취급되는 서브쿼리이다.
- 서브쿼리
- 위치에 따라서 역활이 달라지기 때문에 이름이 달라진다.
인덱스
- 색인
- 데이터 행의 검색 속도를 향상시키기 위해서 사용되는 데이터 베이스 객체이다.
- 데이터의 위치를 빠르게 찾는 신속한 경로 엑세스 방법을 사용하여 디스크의 INPUT/OUTPUT을 줄여준다.
- 인덱스는 테이블과 독립적으로 존재한다.
- 한번 생성된 인덱스는 ORACLE이 자동으로 유지 관리한다.
- 테이블이 삭제되면 그 테이블의 데이터를 색인화하고 있는 인덱스도 같이 삭제된다.
- 인덱스의 생성은
- 자동생성
- 테이블을 정의할 때 PRIMARY KEY(기본키) 제약조건, UNIQUE제약조건이 정의된 컬럼의 값들은 자동으로 인덱스가 생성된다.
- 자동으로 생성이 된다는 것은 제약조건을 자동으로 만들고 관리한다는 것이다.
- 테이블을 정의할 때 PRIMARY KEY(기본키) 제약조건, UNIQUE제약조건이 정의된 컬럼의 값들은 자동으로 인덱스가 생성된다.
- 수동생성
- 사용자가 행에 대한 엑세스 시간을 줄이기 위해서 특정 열을 대상으로 인덱스를 생성할 수 있다.
- 사용자가 특정행에 대한 ACESS의 시간을 줄이기 위해서 특정열을 대상으로 인덱스를 생성한다.
- 병원의 DB의 경우 환자의 번호는 INDEX의 PRIMARY KEY이지만,
환자의 이름은 이름으로 색인 해놓는다.
PRIMARY KEY/ UNIQUE의 키를 동명이인이 존재할 수 있기 때문에 설정하지 못한다. - 쿼리의 실행속도의 향상을 위하여 수동으로 INDEX를 생성할 수 있다.
- 병원의 DB의 경우 환자의 번호는 INDEX의 PRIMARY KEY이지만,
- 그러나 인덱스는 함부로 만들면 안된다.
- 생성이 필요한 경우
- WHERE절이나 조인조건에 자주 사용되는 경우 색인을 지정해주어야한다.
- 컬럼이 매우 다양한 값을 포함하고 있는 경우
- 사람의 이름은 값이 다양하기 때문에 동명이인이여도 일반의원은 1개에서 2개가 나온다.
인덱스로 적합하가.
- 사람의 이름은 값이 다양하기 때문에 동명이인이여도 일반의원은 1개에서 2개가 나온다.
- 데이터가 아주 많은 테이블을 대상으로 조회작업을 했을 때 대부분의 조회작업에서 검색되는 행이 전체 데이터의 2%~4%인 경우
- 만약 여자, 남자로 설정한경우 성별은 50%와 50% 로써 INDEX를 설정할 수 없다
- DATE의 인덱스가 300까지 존재한다면,
데이터가 너무많아서 인덱스의 확인이 불편하고 인덱스로 시간소모가 많이 될 것이다.
- 생성이 필요하지 않는 경우
- 테이블이 작은 경우
- 테이블이 자주 갱신되는 경우
- 인덱스화된 열이 표현식의 일부로 사용되지 않는 경우
- WHERE절의 조회조건으로 자주사용되지 않는 경우
- 대부분의 조회작업에서 전체데이터의 2%~4%이상 검색되는 경우
- 생성이 필요한 경우
- ROWID
- 데이터의 값과 경로를 출력할 수 있는 테이블에서 행의 고유주소를 나타내는 64진수의 숫자데이터이다.
- AAAS83 AAH AAAAIG AAA의 값이 출력된다.
- AAAS83
- 오브젝트 번호 : 테이블에 따라서 다르다
- 테이블이 다르면 Object가 다르다.
- 오브젝트 번호 : 테이블에 따라서 다르다
- AAH
- 파일번호 : 같은 파일에 저장된 번호다
- 테이블이 저장되는 파일이 존재한다.
- 테이블의 파일 번호가 달라진다.
- 실제 데이터가 저장되어 있는 슬록번호이다.
- AAAAIG
- 블록번호
- AAA
- 행번호 : 슬록번호
- 파일내부에 여러블록으로 나눠놓고 실제적인 주소를 ROWID를 통하여 알 수 있다.
- 인덱스는 ROWID와 연관성이 있다.
- 인덱스 명에는 IDX을 많이 붙인다.
- 인덱스의 색인위치에 ROWID의 값위치가 들어간다. TREE형태로 인덱스의 PRIMARY KEY 값으로 정렬된다.
- 양쪽값이 균등하지 않는다면 균형이 맞지 않아
2000번 이상을 빨리 찾게 되고
2000번은 더 늦게 찾게되지 않을까?- 양쪽값이 균등하도록 조정해서 고루 분포되게 균형잡힌 트리가 될 수 있도록
- 오라클에서 인덱스에 대해서 알아서 관리하고 있다.
- INDEX는 항상 정렬되어있으며, 색인 또한 정렬이 되어있다.
- 색인이 만들어져있기 때문에 옵티마이저의 COST의 비용도 덜 발생된다. : INDEX설정시
- 현재 2초의 COST발생의 경우 해당 TABLE의 다른 테이블에도 동일한 이름이 있기 때문에 확인으로 2초의 COST가 발생된다.
- 오라클의 계획설명
- RDBMS 는 옵티마이져가 구동되는 중이다.
- SQL을 전달받고 어떻게 실행할지 SQL을 분석 후 최적의 실행방법을 분석한다.
그리고는 실행계획을 수립한다.
옵티마이저의 실행계획이 실행되고, 위에처럼 COST처럼 설명이 나온다.
- SQL튜닝 과 분석 : 최적의 쿼리를 작성하면서 인덱스를 추가한다.
- 오라클의 힌트
- 옵티마이저는 사람보다는 똑똑하지 않다.
- 옵티마이저를 분석하고, 실행분석을 수립하고, 가이드를 만들 때 옵티마이저힌트를 작성하여 포함한다.
-
이러한 형태로 옵티마이저에게 힌트를 전송한다.
개발자의 의도를 옵티마이저에게 전달하여 실행계획 수립시 도움을 준다.
- 인덱스를 사용하지 않으면 COST가 증가되고, 쿼리의 실행가능이 떨어진다.
- INDEX사용시 쿼리의 성능을 높일 수 있다.
- 오라클의 힌트
- AAAS83
서브 쿼리
- 서브쿼리란 메인 쿼리내부에 정의된 쿼리이다.
- 다른 SELECT문의 내부에 정의된 SELECT문을 서브쿼리라고 한다.
- 서브쿼리를 포함시킬 수 있는 곳
- WHERE절
- SELECT절
- HAVING절
- FROM 절(인라인 뷰)
- SELECT COLUMN, COLUMN
FROM TABLE
WHERE COLUMN 연산자 (SELECT COLUMN FROM TABLE);- 오른쪽의 위치에 위치한다.
- 실행결과는 메인쿼리의 WHERE절(조건식)에서 사용된다.
- 쿼리를 통해서 획득할 수 있는 값으로 조건식을 사용해야한다.
- 서브쿼리는 반드시 괄호로 묶여야한다.
- 종류는 결과가 몇개나오는지에 따라서 달라진다.
- 다중행
- 연산자가 여러개이면 다중행이다.
- 서브쿼리의 실행결과로 여러행이 반환된다.
- 단일행
- 연산자가 하나면 단일행이다.
- 서브쿼리의 실행결과로 한행만 반환된다.
- 지금까지 작성한 것이 단일행 서브쿼리이다.
- WHERE절이나 HAVING절에서 사용되는 서브쿼리는 조건식의 사용될 값을 제공한다.
- 조건식에서 사용되는 값이 SQL실행으로 획득되는 경우에는 서브쿼리를 사용한다.
-
단일행 서브쿼리 다중행 서브쿼리 = IN <> NOT IN > >ANY,>ALL < <ANY, <ALL
- 서브쿼리의 특징
- 서브쿼리는 한번만 실행된다.
- 서브쿼리는 메인쿼리보다 먼저 실행된다.
- 서브쿼리의 실행결과는 메인쿼리의 조건식에서 사용된다.
- 조건식에서 비교값으로 사용되는 값이 쿼리의 실행결과로만 획득할 수 있을 때, 그 비교값을 조회하는 쿼리가 서브쿼리다
- 서브쿼리 사용시 주의점
- 서브쿼리는 반드시 괄호로 묶여야한다.
- 조건식의 오른쪽에 서브쿼리를 위치시키면 가독성이 높아진다.
- 서브쿼리의 실행겨로가가 단일행인지 다중행인지에 따라서 적절한 연산자를사용해야한다.
- 괄호가 되어잇는 부분이 먼저 실행되고, 항목이 1개이기 때문에 단일행 서브쿼리이다.
- 좌우가 컬럼의 갯수가 같아야한다.
- 하나의 문장에 서브쿼리가 2개가 올 수 있다.
- 다중행 서브쿼리
- 조건의 결과가 다중행이다.
다중행 서브쿼리
- 조인은 한쪽에 있는 것이 나오지 않는다.
- 양쪽에 있어야만 결과가 나온다.
- 조인을 사용할 수 있으면 서브쿼리보다 조인을 사용하는 것이 좋다.
- 서브쿼리보다 조인을 장려한다.
- 값을 가공없이 사용할 때는 JOIN을 사용하는 것이 좋다.
- 조인으로 풀수 있는 것은 서브쿼리로 사용할 수 있지만 서브쿼리의 값을 MAIN쿼리에서 가져올 수 없다. ㄱ
- 괄호안에서만 사용하고 끝이기 때문이다.
- 조인으로 풀리는 것이 더 많기 때문에 되도록 조인을 사용하는 것이 좋다.
- ALL : 서브 쿼리로 조회된 급여보다는 무조건 전체보다 높아야한다는 의미 ALL
- SELECT *
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 60
AND SALARY > ALL(SELECT SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 30); - SELECT *
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 60
AND SALARY > (SELECT MAX(SALARY)
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 30); --->ALL은 MAX와 동일하다.
- SELECT *
- ANY : 서브쿼리중 하나라도 높으면 나온다.
- SELECT *
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 60
AND SALARY > ANY(SELECT SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 30); - SELECT *
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 60
AND SALARY > (SELECT MIN(SALARY)
FROM EMPLOYEES
WHERE DEPARTMENT_ID = 30); --->ANY는 MIN과 동일하다.
- SELECT *
다중열 서브쿼리
- SELECT *
FROM TABLE
WHERE (COL1, COL2) IN (SELECT COL3, COL4
FROM TABLE) - 여러열을 연결하고 연산자는 IN을 사용해서 서로 비교를 함
- 자신이 소속된 부서에서 최저급여를 받는 사원의 부서아이디, 사원아이디, 급여를 조회하기
- 부서에서의 최저급여받는 사람을 서브쿼리로 둬서 사원을 비교하여 조회하겠다
- SELECT DEPARTMENT_ID, EMPLOYEE_ID, FIRST_NAME, SALARY
FROM EMPLOYEES
WHERE (DEPARTMENT_ID, SALARY) IN(SELECT DEPARTMENT_ID, MIN(SALARY)
FROM EMPLOYEES
WHERE DEPARTMENT_ID IS NOT NULL
GROUP BY DEPARTMENT_ID)
ORDER BY DEPARTMENT_ID ASC;
- HAVING절에서 서브쿼리 사용하기
- HAVING절에서 부서별 사원수를 조회했을 때 사원수가 5명이하인 부서의 아이디와 사원수를 조회하기
- SELECT DEPARTMENT_ID, COUNT(*)
FROM EMPLOYEES
WHERE DEPARTMENT_ID IS NOT NULL
GROUP BY DEPARTMENT_ID
HAVING COUNT(*) <= 5
ORDER BY 1; - 그룹그룹을 지어놓고 COUNT를 적용시켜서 사용함 5명이하는 HAVING을 사용해서 출력함
- WITH절
- SQL의 실행결과를 지정된 이름으로 임시보관(캐싱)한다.
- 서브쿼리를 사용하는 SQL문에서 반복적으로 실행되는 SQL에 대해서 WITH절을 사용하면 실행 성능이 향상된다.
- WITH절에서 정의한 가상의 테이블의 아래 SELECT문을 사용할 수 있다.
- WITH절은 단독으로 사용할 수 없다.
- WITH 해당하는 FROM절에 사용하는 인라인뷰, 일반 뷰이다.
- 가상의 테이블이라는 의미다.
- WITH절을 만들면 SELECT로 전테를 사용할 수 있게 된다.
- WHERE절에서도 사용이 가능하다.
- COUNT(*)절로 반복적으로 사용된다.
- WITH 별칭1
AS (SELECT 문),
별칭2
AS (SELECT 문)
SELECT COL, COL
FROM 별칭1, 별칭2로 가져와서 사용하면 된다.
WHERE조건식- WITH EMP_SALARY
AS(
SELECT DEPARTMENT_ID AS DEP_ID, AVG(SALARY) AVG_SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID IS NOT NULL
GROUP BY DEPARTMENT_ID
)--여기까지는 맞춤
SELECT DAS.DEP_ID, E.EMPLOYEE_ID, E.FIRST_NAME, E.SALARY, DAS.AVG_SALARY
FROM EMPLOYEES E, (SELECT DEPARTMENT_ID AS DEP_ID, AVG(SALARY) AVG_SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID IS NOT NULL
GROUP BY DEPARTMENT_ID) DAS
WHERE E.DEPARTMENT_ID = DAS.DEP_ID
AND E.SALARY > DAS.AVG_SALARY; - 인라인뷰로 사용이 가능하다.
- SELECT DAS.DEP_ID, E.EMPLOYEE_ID, E.FIRST_NAME, E.SALARY, DAS.AVG_SALARY
FROM EMPLOYEES E, ( SELECT DEPARTMENT_ID AS DEP_ID, AVG(SALARY) AVG_SALARY
--표현식은 별칭을 사용할 것
FROM EMPLOYEES
WHERE DEPARTMENT_ID IS NOT NULL
GROUP BY DEPARTMENT_ID) DAS
WHERE E.DEPARTMENT_ID = DAS.DEP_ID
AND E.SALARY > DAS.AVG_SALARY;
- SELECT DAS.DEP_ID, E.EMPLOYEE_ID, E.FIRST_NAME, E.SALARY, DAS.AVG_SALARY
- WITH EMP_SALARY
반응형
'중앙 HTA (2106기) story > JDBC story' 카테고리의 다른 글
트랜잭션, 에러찾기 tip,select문 tip (0) | 2021.11.02 |
---|---|
상호연관서브쿼리, 분석함수, 계층, 권한분석 (0) | 2021.11.02 |
DDL (0) | 2021.10.27 |
join, 정규화 간단 (0) | 2021.10.27 |
SQL 내장함수, 서브쿼리 (0) | 2021.10.25 |
Comments