43
2
index_asc이기 때문에 항상 오름차순으로 간다.
시작점은 deptno = 20, sal=2000이다. 오름차순이고, 조건이 comm<=100이기 때문에 comm=100에서 시작할 순 없다.
만약 comm >= 100이 조건이었다면 deptno = 20, sal=2000, comm>=100이었을 것이다.
44
4
range scan을 하려면 선두 칼럼이 조건절에 있어야 한다.
3번의 경우 오라클은 하나만 null이 아니면 인덱스에 저장하기 때문에 가능하다.
4번은 deptno가 아예 없으므로 range scan 이 불가능하다.
45
4
고객등급이 in-list로 적혀있으므로 skip scan으로 동작하지 않는다.
고객등급에 대해 3번씩 random access가 될 것이다.
46
2,4
1 - 선두칼럼인 deptno가 없으므로 불가능하다.
3 - 인덱스 칼럼이 아닌 칼럼들이 있으므로 불가능하다.
따라서 4번으로 skip scan하거나 2번 full scan해서 sal로 필터링을 할 것이다.
둘 중 더 효율적인 방법으로 옵티마이저가 고를 것이다.
47
1
비트맵이냐 B+Tree냐는 rowid를 찾아가는 탐색 과정에 차이가 있지, random access 줄이는 것이랑은 딱히 상관이 없다.
48
2
NDV가 높은 순서대로 인덱스를 구성하는 것이 좋다. NDV가 높다는 것은 '=' 조건의 선택도가 아주 적다는 것이고, 많은 레코드를 거를 수 있다는 것이다.
49
3
1 - 인덱스가 주문일자 밖에 없기 때문에 주문일자 조건만으로 인덱스 탐색이 이루어진다.
2 - 마찬가지 이유로, 배송상태를 필터링 하려면 테이블 액세스 해야 한다.
3 - select절에 고객ID, 연락처가 포함됐기 때문에 어쨌든 테이블은 봐야 한다.
4 - 배송상태='ING' 선택도가 낮다면 필요한 레코드 수에 비해 random access 수가 많다는 것이다. 주문일자와 배송상태를 결합하면 좋다. 칼럼 통계가 문제에서 주어지지 않았기 때문에 순서는 모른다.
50
1, 3
전 후의 쿼리에서 가입일자가 like이기 때문에 이걸 선두 인덱스로 쓰면 별로 좋지가 않다.
1 - 가입일자로 스캔을 두 번 하기 때문에 인덱스 스캔 시 블록 I/O가 늘어난다. 고객등급이 인덱스에 없어서 테이블 random access도 두 배로 는다.
2 - 같다. 늘진 않는다.
3 - 1번과 같은 이유로 인덱스 스캔 I/O가 두 배로 늘어난다.
4 - 엄청 줄어든다.
51
2, 4
index range scan 해서 찾은 row 수는 266476이고, 이후 테이블 액세스에서 266468개 블록을 접근한다. (cr = consistent read block)
이는 클러스터링 팩터가 안 좋다는 뜻이다.
또한 인덱스에 칼럼을 추가하면 테이블의 random access를 줄일 수 있다.
참고
52
3
참고
53
3
ordered 를 썼기 때문에, 고객부터 본다. 실제로 실행게획에서도 고객 먼저 접근하는 것을 확인할 수 있다.
고객을 가입일자로 먼저 접근해서 (고객_X01의 선두는 아마 가입일자일 것이다) 고객 번호를 포함한 고객에 대한 정보를 가져온다. 그리고 그 고객번호와 주문일자로 주문 테이블에 접근할 것이다.
인덱스가 주문일자, 고객번호이기 때문에 그 순서로 접근한다.
54
2
고객 테이블 먼저 드라이빙하는데, 인덱스에서 테이블로 접근해서 2978개 row 읽었는데 막상 필터링 되는 결과는 23개 밖에 안 된다. 고객_IDX가 현재 고객등급인지 연령인지 모르겠지만, 어쨌든 둘 다 인덱스에 포함해주면 인덱스 탐색 단계에서 많이 필터링해서 불필요한 테이블 액세스를 줄일 수 있을 것이다.
55
3
1 - 고객ID는 PK지만 SUBSTR로 가공했으므로 range scan이 불가능하다.
2 - 직업코드가 누락됐으므로 range scan이 불가능하다.
3 - 가능하다. 고객명이 null이 아닌 값들은 인덱스에 등록되기 때문이다.
4 - 고객ID는 문자열이다. 오라클은 문자를 NUMBER로 바꾸려는 경향이 있으므로 고객ID를 비교하기 위해서 문자열로 묵시적 형변환이 일어날 것이다. 결국 가공이 일어났으르모 range scan이 불가능하다.
56
1, 3
57
2, 3
1 - 해시이기 때문이다.
2 - build input은 작은 테이블로 선정한다.
3 - CPU, 메모리 사용이 크기 때문에 수행빈도가 낮은 OLAP에서 적합하다.
4 - 중복값이 많으면 해시 체인이 커진다.
58
4
shared pool은 여러 세션이 공유하기 때문에 적합하지 않다.
PGA의 Query Execution Cache에 저장한다.
59
3
두 SQL문은 A일부터 B일까지 판매된 것들 중, C일부터 판매 시작한 상품의 판매금액과 수량을 통계 내는 쿼리이다.
1 - NL Join이기 때문에 가능한 이야기이다.
2 - 현재 일별매출 a 테이블이 드라이빙 되고 있는데, 판매시작일자 조건을 만족하는 범위가 적다면, b 테이블을 먼저 드라이브 해서 조인을 줄일 수 있다.
3 - C일이 최근에 가깝다면 A일부터 볼 필요 없이 C일부터 B일까지 보면 된다. 어차피 A~B 구하고 이를 C 이후의 것만 필터링 할 거라면 비효율이 늘어난다.
4 - 실행계획을 보면 필터링이 Nested Loop 의 inner에 있다. SQL1보단 SQL2가 좋을 수도 있기 때문에 옵티마이저는 SQL2과 유사한 실행계획을 수립하기도 한다.
60
2
NL 조인이나 Sort Merge Join은 효율적이건 아니건 간에 항상 가능하다.
다만 Hash Join은 sal이 =이 아니기 때문에 불가능하다.
61
3
선분이력에선 값을 between 시작 and 끝 으로 조회하면 된다.
1번은 점이력에서 저렇게 한다.
----- 파티션 내용
62
3
1 - 테이블 파티션과 1:1 대응이 되도록 DBMS가 신경 써준다.
2 - 테이블 파티션과 1:1 관계이기 때문에 테이블 파티션에 변경이 일어나면 인덱스 파티션도 변경되어야 한다.
3 - 파티션 키가 인덱스 선두칼럼이 아니거나 조건절에 파티션 키가 없는 경우를 nonprefixed 인덱스 파티션이라고 한다.
오라클에서 global nonprefixed는 안 되는데 local prefixed는 된다.
4 - 테이블 파티션 키가 SQL 조건절에 없다면 결국에 테이블 파티션 다 봐야 해서 비효율이 생긴다. Local 파티션 인덱스의 경우 테이블 파티션 키가 인덱스 파티션이 된다.
63
1, 2
매출연월 기준으로 파티션을 고르게 분산하려면 range와 list가 가능하다.