쿼리에서 binding하는 구문(? 가 들어가서 이 부분이 place holder로서 작용하는 부분)이 있을 시 범위 질의에서 플랜이 달라지는 경우가 발생한다. 플랜이 하나로 될 수 있음에도 둘로 갈라지면서 성능이 느려질 수 있는 부분이 있다.
위의 경우에 대해서 아래 3가지를 비교하면서 그 차이를 설명한다.
1.Where절에 조건을 상수로 준 경우 => range plan 1개
String sql = "select nation_code from participant where host_year >= 2004 and host_year <= 2008";
seg[0]: [0]
seg[1]: nation_code[0] (f)
seg[2]: host_year[0]
Join graph nodes:
node[0]: participant participant(916/16) (sargs 0)
Join graph terms:
term[0]: participant.host_year range (2004 ge_le 2008) (sel 0.0588235) (rank 2) (sarg term) (not-join eligible) (indexable host_year[0]) (loc 0)
2.Where절에 조건을 “?+상수”로 준 경우 => range plan 2개
String sql = "select nation_code from participant where host_year >= ?+4 and host_year <= ?+8";
seg[0]: [0]
seg[1]: nation_code[0] (f)
seg[2]: host_year[0]
Join graph nodes:
node[0]: participant participant(916/16) (sargs 0 1)
Join graph terms:
term[0]: participant.host_year range (min inf_le 2008) (sel 1) (rank 2) (sarg term) (not-join eligible) (indexable host_year[0]) (loc 0)
term[1]: participant.host_year range (2004 ge_inf max) (sel 0.0588235) (rank 2) (sarg term) (not-join eligible) (indexable host_year[0]) (loc 0)
3.Where 조건을 “?”로 준 경우 => range plan 1개, 1.의 경우와 같음.
String sql = "select nation_code from participant where host_year >= ? and host_year <= ?";
seg[0]: [0]
seg[1]: nation_code[0] (f)
seg[2]: host_year[0]
Join graph nodes:
node[0]: participant participant(916/16) (sargs 0)
Join graph terms:
term[0]: participant.host_year range (2004 ge_le 2008) (sel 0.0588235) (rank 2) (sarg term) (not-join eligible) (indexable host_year[0]) (loc 0)
1과 3의 경우는 >와 < 의 범위질의를 하나로 처리하는 모습이 보인다. participant.host_year range (2004 ge_le 2008)
2는 이와 달리, participant.host_year range (min inf_le 2008) 와 participant.host_year range (2004 ge_inf max) 의 두 가지로 범위질의를 나누어 처리하게 된다.
이 결과에 따르면 플랜은 처음 작성된 쿼리 문장 자체를 가지고 작성하게 된다. 따라서, ? 부분이 binding 되기 이전에 플랜을 작성하는 것이므로 이렇게 다르게 플랜이 나오는 것은 그 동작이 자연스러운 결과라 할 수 있다.
쿼리를 작성할 때 좀더 최적화된 형태를 고려한다면, ? 로 binding 되는 부분이 연산된 결과의 값으로 작성하는 것이 유리하다 하겠다. 요약하면, ?+ 상수 형태로 값을 넘기는 것 보다는 값을 미리 계산한 결과값을 ?에 전달하는 것이 최적화된 쿼리라 하겠다.
즉,
보다
select nation_code from participant where host_year >= ? and host_year <= ?
이 더 최적화된 쿼리라 할 수 있다.