서울대학교 데이터사이언스대학원 정형수 교수님의 "데이터사이언스 응용을 위한 빅데이터 및 지식 관리 시스템" 강의를 필기한 내용입니다.

  • Logical query plan 에서 physical plan 으로 바꿀 때에는 model 을 이용해 cost 를 계산해서 처리하며 이것을 Cost-based search 라고 한다.
    • 이때는 동등한 query 여럿을 비교해서 cost 가 제일 작은 것을 취한다.
    • 여기서의 cost 는 estimation 이다: 당연히 진짜 cost 를 계산하지는 못하고 “추정” 하게 된다.
  • 이것은 (1) Cost estimation (2) plan enumeration 두 단계로 이루어진다.

Cost Estimation

Cost Model

  • Cost 는 대략 세가지 정도로 나눌 수 있다.
    • Physical Cost: CPU cycle, IO, Memory consumption 등
    • Logical Cost: 각 Operator 당 result 의 size 를 estimation 하는 것
    • Algorithmic Cost: 쉽게말해서 시간복잡도
      • 이건 disk-based 에서는 별로 중요하지 않지만, in-memory DB 에서는 이놈도 동등하게 중요해진다고 한다.
  • 여기서 disk-based DBMS 의 주된 cost metric 은 IO 이다: 어떤 (JOIN 등의) algorithm 을 선택했을때 disk-mem 간의 data movement 가 가장 적을 것이냐
    • 뭐 당연히 sequential 이 random 에 비해 훨씬 좋고
    • 만약 direct IO 등으로 DBMS 가 buffer 에 대한 모든 권한이 있다면 estimation 하기가 훨씬 쉬워진다.
  • Cost model 은 생각보다 잘 안맞는다고 한다.
    • 왜냐면 client 가 한명이 아니기 때문
    • Resource contention 이 걸려서 sequential IO 일 지라도 여러 client 가 모이면 random IO 이나 다를바가 없어지는 상황이 된다.
    • 이것을 줄이기 위해 resource 를 격리하는 performance isolation 이 estimation 에서 중요하다고 할 수 있다.

Cost Models for DBMS

  • PostgreSQL: database 가 disk 에 있고, memory 가 별로 크지 않은 상황을 가정하고 CPU 와 IO cost 의 조합으로서 cost 를 계산한다.
    • 여기에는 Magic 이라는 상수값이 관여된다고 한다.
  • IBM DB2: 여기에서는 system catalog 를 통해 알아낸 database 의 특성, HW 정보 (CPU, memory, storage device 등에 대한 microbenchmark) 등을 고려한다고 한다.

Statistics

  • DBMS 는 자신의 information schema 에 statistics 를 저장하고 cost estimation 에 활용한다고 한다.
  • ANALYZE 라는 문법으로 특정 query 에 대한 cost estimation 을 볼 수 있는데, 이것으로 manual 하게 statistics 를 update 할 수 있다고 한다.
  • 그럼 DBMS 에서 저장하는 statistics 를 보면, 일단 어떤 relation 에 대해:
  • : Relation R 의 tuple 개수
  • : Relation R 의 attr A 의 unique value 개수
  • : Selection Cardinality - Attribute A 의 각 unique value 에 대한 개수 평균
    • 따라서 다음의 수식으로 계산될 수 있다.
    • 다만 이 수식은 uniform distribution 을 기본으로 깔고 가지만 당연히 uniform 하지 않을 수 있기 때문에 더 복잡한 cardinality estimation 방법이 필요하다고 할 수 있다.

Selection Factor, Selectivity

  • : Selection Factor (Selectivity) - 전체 tuple 중 predicate 에 부합하는 tuple 의 비율
    • 그래서 predicate 가 없으면 factor 는 1 가 된다.
  • 이놈을 계산하는 방법은 predicate 의 type 에 따라 달라진다.
  • Uniform distribution 에 대해, 이것을 계산하는 방법에 대해 알아보자.

Uniform Scenario

Equality Predicate (Exact Match)
  • 는 predicate 에 부합하는 tuple 의 비율인데, uniform distribution 이라면 equality predicate 에 대한 는 다음과 같이 계산할 수 있을 것이다.
  • 이건 생각해보면 당연한 것이다.
    • Uniform distribution 이기 때문에, 모든 unique value 에 대해 해당 값을 가지는 tuple 의 개수는 로 동일할 것이다.
    • 따라서 어떤 predicate 를 들이밀어도 그것이 equality 라면 이것에 부합하는 tuple 의 개수는 항상 으로 고정일 것이고, 따라서 저런 수식이 되는 것.
  • 만약에 uniform distribution 이 아니라면 당연히 얘기는 달라진다.
    • 값은 평균이기 때문에 어떤 unique value 에 대해 해당 값을 갖는 tuple 들의 개수는 이 아닌 그 unique value 가 뭐냐에 따라 달라진다.
    • 따라서 이때는 저 수식으로는 계산할 수 없게 된다.
  • 가령 예를 들어보면 , 으로 으로 균일한 uniform distribution 에 대해 histogram 을 그려보면 다음과 같이 될 것이다.

  • 따라서 라는 predicate 을 들이밀었을 때 그것에 부합하는 tuple 은 1개이므로 가 되는 것.
Range Predicate
  • 마찬가지로, 만약 uniform distribution 이라면 range predicate 의 를 계산하는 것도 한결 쉬워진다.
  • 만약 라는 predicate 에 대해, unique value 중에서 보다 크거나 같은놈이 개라면, 다음과 같이 될 것이다:
  • 예시로 이해하면 쉽다: 다음과 같은 histogram 이 있을 때

  • 에 대해 2보다 크거나 같은놈이 3개 있고 모든 unique value 에 대한 count 가 로 동일하므로 이다.
Negation, Conjunction, Disjunction
  • 보면 저 라는 놈이 “확률” 인 것을 알 수 있을 것이다.
  • 따라서 Negation (NOT ...), Conjunction (... AND ...), 그리고 Disjunction (... OR ...) 이 다음과 같이 계산되리라는 것을 알 수 있다.
Assumptions
  • 위의 수식들에 대해서는 다음과 같은 가정이 있다:
    • Uniform distribution: 위에서도 말한 대로, uniform distribution 이어야 해당 수식들이 들어맞는다.
    • Independent predicates: 확률에서처럼 위의 수식들이 유도되었기에, 확률론에서 말하는 것처럼 쟤네들은 독립실행이어야 한다. 즉, attribute 들이 independent 해야 한다.
    • Inclusion Principle: 사실 이건 뭔말인지 잘 모르겠음
Correlated Attributes
  • 두 predicate 를 AND 하면 곱하여 sel 을 구할 수 있겠지만
  • 두 predicate 의 attribute 들이 상관관계가 있으면 이 sel 은 틀리게 된다.
  • 가령 accord 는 honda 에서만 출시되는 자동차 모델이기 때문에
    • 이때의 sel 은 car_model 에 대한 sel 만으로 산정하는 것이 맞고
    • car_maker 와 car_model 각각에 대한 sel 을 곱하여 산정하면 틀린 것
    • 즉, car_model 을 알면 car_maker 가 특정되는 상황에서는 attribute 들이 independent 하지 않기 때문에 위 수식이 맞지 않게 된다.

Non-uniform Approximate

  • 지금까지는 uniform distribution 을 가정했는데, 실제로는 당연히 그렇지 않다.
  • 따라서 non-uniform distribution 을 생각해 보자.
  • 여기서는 histogram 을 그릴 때, 각 unique value 에 대한 statistics 를 구하면 당연히 좋겠지만 그건 아무래도 힘드니까
  • “Bucketing” 을 하고, 이 안에서는 uniform 하다고 가정하여 approximate 한 histogram 을 그려 를 추정하게 된다.
    • Histogram 만 있으면 을 구하는건 쉽다.
    • 컴퓨터가 계산하기 위한 알고리즘은 잘 모르겠지만 그래도 사람이 보고 계산하는 것은 쉬우니까 설명은 생략
Equi-width Histogram
  • 전체 unique value range 를 등분해서 bucketing 하는 방법
  • 그래서 bucket size 가 작을수록 정확해지긴 한다. 물론 overhead 가 있지만
  • 가령 다음과 같은 histogram 을

  • 이렇게 approximate 하는 것이다:

Equi-depth Histogram
  • 이건 각 bucket 들의 count 가 균등해지도록 (1~2차이) bucket 의 range 를 다르게 가져가는 것을 말한다.
  • 가령 다음과 같은 histogram 은

  • 이렇게 approximate 된다.

Sketching
  • Sketch 라는 것은 histogram 처럼 probabilistic 한 정보를 담는 자료구조로, data set 에 대한 approximated statistics 를 제공해 준다고 한다.
  • Histogram 을 sketch 로 교체해 estimation 의 정확성을 좀 더 높일 수도 있다고 하네
Sampling
  • BtrBlocks 에서처럼 몇개를 랜덤추출해서 statistics 를 구하는 것을 말한다.
  • Progressive sampling: 이전 query 에서의 statistics 결과를 계속 누적해서 점차 정확해지게 하는 것을 말한다.
    • 참고로 이렇게 progressive 하게 진행하는 알고리즘을 emortization 라고 부른다.

Summary of Cost Estimation

  • 간단라멘으로 요약하면 Cost 는 크게 physical, logical, algorithm 으로 나눌 수 있고
  • Disk-based 에서 physical cost 에서는 IO 가 전부라고 했다.
  • 그리고 logical cost 는 각 plan node 의 result size 를 selectivity 로 estimate 하는데
    • 이때는 non-uniform 인 상황에 대해서 Equi-W Histogram, Equi-D Histogram, Sketch, 그리고 Sampling 등으로 distribuition 을 approximate 하여 를 구할 수 있다.
  • 마지막으로 각 node 내에서의 computation overhead 를 algorithm cost 로 estimate 할 수 있다.

Plan Enumeration

  • 그럼 cost 는 위에 소개한 방식으로 계산한다고 치고, 실질적으로 여러 plan 을 저 cost 로 비교하는 방법에 대해 알아보자.
    • 여기서는 모든 plan 에 대해 비교하거나, 아니면 timeout 을 둬서 해당 timeout 까지 비교한 plan 들에 대해 가장 cost 가 적은 놈을 선택한다.
  • 크게 (1) Single-relation, (2) Multi-relation, (3) Nested sub-query 로 경우의 수를 나눌 수 있다.
    • 인데, (3) 은 안다루고 (1) 하고 (2) 에 대해서만 다루는듯 하다.

Single-relation Query

  • Single relation access 를 하는 OLTP query 는 sequential, binary (clustered index), index search 중에서 heuristic 으로 골라서 사용해도 충분하다고 한다.

Multi-relation Query

  • JOIN path 가 길어질수록 당연히 alternative plan 들도 많아진다.
  • 이때 결정할 것은 다음의 3가지 이다:
    • 어떤 순서로 JOIN 할 것이냐 (JOIN ordering)?
    • 어떤 알고리즘으로 JOIN 할 것이냐 (NLJ, SMJ 등등)?
    • 어떤 access method 를 사용할 것이냐 (sequential scan, index scan 등등)?

IBM System-R Approach

  • 이 방법은 JOIN ordering 에만 연관이 있긴 한데, 이전의 System R 에서는 left-deep tree 의 원칙으로 plan 을 짠다고 한다.
  • 가령 다음과 같은 세 plan 이 있을 때,

  • 가장 왼쪽의 plan 을 선택한다는 것: 즉, 가장 왼쪽으로 skew 된 plan 을 선택한다고 생각하면 된다.
  • 이렇게 하면 fully-pipelined plan 이 될 수 있다고 한다.
    • 여기서 pipeline 은 volcano model 을 생각하면 될듯
    • 뭐 child 의 next() 를 차근차근 가져오는게 용이하다 정도로 이해하면 된다.
  • 이 경우에는 plan 을 정확히 맞추지는 못하지만 어느정도 쓸만한 성능이 나온다고 한다.
    • 다만 생각보다 모든 left-deep tree 가 fully-pipeline 인 것은 아니어서 요즘은 많이 안쓴다고 한다.

Dynamic Programming

  • 또 다른 방법으로는 dynamic programming 으로 JOIN ordering 과 JOIN algorithm 을 구하는 것이다.
  • 다음의 예시를 보자.

  • 오른쪽의 SQL 을 참고하면, 우선 첫번째로 JOIN 하는 것은 이거나 일 것이다.
  • 그리고 각각에 대해, HJ 및 SMJ 에 대한 cost 를 메겨 보면 위와 같이 된다고 해보자.
  • 그럼 이때 path (빨간색 화살표) 는 4가지가 있다. 여기에서, 각 JOIN 순서에 대해 cost 가 적은 것을 택한다.
    • 에 대해서는 HJ 가 더 cost 가 적으니까 이걸 선택하고, 에 대해서도 HJ 가 더 cost 가 적으니까 이걸 선택한다.
  • 따라서 다음에는 이렇게 된다.

  • 에 대한 JOIN algorithm 이 하나씩 정해진 것을 볼 수 있고,
  • 이번에는 각각의 JOIN 에 대해 다음번의 JOIN 인 로 가는 path 도 2개씩 더 (총 4개 더) 있는 것을 볼 수 있다.
  • 이때에도 마찬가지로 cost 가 적은 것을 고르면 에서는 HJ, 에서는 SMJ 가 선택된다는 것을 알 수 있다.
  • 즉, 이렇게 되는 것

  • 마지막으로 도합 cost 가 적은 path 를 선택하면 최종적으로 가 된다는 것을 알 수 있다.

Candidate Plans

  • 이게 아마 지금 MySQL 이 사용하고 있는 방법인것 같다.
  • 우선 JOIN tree 를 모두 그려보고 그중에 하나를 고른다.

  • 다음에는 각 JOIN 의 algorithm 을 고른다.

  • 마지막으로는 access methods 를 결정하는 순서로 진행된다.

  • 물론 이건 간단하게만 말한거고, 실제로는 훨씬 복잡하다고 한다.

PostgreSQL Genetic Optimizer

  • PostgreSQL 에서는 query 에 관여하는 table 의 개수가 12 보다 작으면 그냥 dynamic programming 을 이용하지만, 12보다 커지면 Genetic Query Optimizer (GeQO) 를 사용한다고 한다.
  • GeQO 에서는 plan tree 를 그려보고 cost 를 구해서 가장 worst 인 놈을 버리고 나머지 애들을 좀 변형시켜서 다시 cost 구해서 worst 를 버리는 식으로 진쟇된다.
    • 즉, local min 을 구하는 것과 비슷한 과정으로 min cost 를 찾아가는 셈이다.
  • 가령 예를 들면 1st generation 에서 plan 세개를 그리고, 이때의 최악인 첫번째를 거른다.

  • 그리고 2nd generation 에서는 이전 query 를 변형해 plan 들을 만들고, 이때도 가장 안좋은 놈을 거른다.

  • 3rd generation 에서도 마찬가지다.

  • 이런식으로 점차 구해나가는 방법을 이용한댄다.