7.4.7 GROUP BY, ORDER BY, 7.4.9 서브쿼리

RealMysql 2013.01.07 17:58 posted by dev.bistro

7.4.7 GROUP BY

- "특정 칼럼의 값으로 레코드를 매핑", "각 그룹의 집계된 결과를 하나의 레코드로 조회할 때 사용"


* MySQL은 그룹 키가 아닌 칼럼이더라도 집합함수없이 GroupBy에 사용할 수 있지만, 제대로 된 사용은 아니다.

- SELECT  first_name FROM employees GROUP BY gender;

-- gender로 그루핑을 해서 M/F 2개의 결과로 묶지만 SELECT는 first_name이다. 이게 M/F그루핑한것중 최소/최대/중간값인지 알수없다.

-- "이러한 사용은 가독성 저하" ==> 반드시 GROUP BY에 명시되지 않은 칼럼은 집합함수로 감싸라.

-- 이렇게 집합함수를 감싸서 사용할 수 있게 하는것을 'FULL_GROUP_BY' , 옵션으로 enable가능하다.


* GROUP BY .. ORDER BY NULL

- MySQL의 GROUP BY는 '그루핑 칼럼 순'으로 정렬까지 수행한다. 정렬이 필요없다면 "ORDER BY NULL"을 추가


* GROUP BY col1 ASC col2 DESC

- MySQL의 GROUP BY가 정렬도 수행하기 때문에 이처럼 정렬 순서도 명시할 수 있다.

- 이것도 ORDER BY와 동일하기 때문에, 정렬순서가 혼용되면 인덱스 사용이 불가능하다.

- 많은 사용자가 익숙치 않기 때문에 그냥 ORDER BY에서 사용하자.


* GROUP BY .. WITH ROLLUP

- 그루핑된 그룹별로 TOTAL COUNT를 가져올수 있는 기능.


* 레코드를 칼럼으로 변환해서 조회

- 레코드를 칼럼으로 변경

- 하나의 칼럼을 여러 칼럼으로 분리 을 할 수 있다 (ref: 468page)


7.4.8 ORDER BY

* 만약 ORDER BY가 없다면 기본 정렬 상태는 ?

- 인덱스를 사용하면, 인덱스의 정렬 순서대로

- 인덱스 사용 X, 풀테이블 스캔

-- MyISAM : 저장된 순, 단 INSERT순은 아니다. 빈 공간이 있으면 거기에 저장하기 때문

-- InnoDB : 항상 PK로 클러스트링 되어서, 풀 스캔의 경우 기본 PK 순으로 가져옴

- SELECT가 임시테이블을 거친다면 순서를 예측할 수 없다.



* ORDER BY 사용법 및 주의사항

- ORDER BY 2 : 2번째 필드로 정렬

- ORDER BY "var" : MySQL은 ""로 묶인 문자열은 무시한다. <- 주의하자.


* ORDER BY RAND()

- 단순추첨, 임의사용자 조회를 위한 가장 단순한 방법

- '절대' 인덱스를 이용할 수 없다.


* 여러 방향으로 동시 정렬

- 오름/내림차순이 혼용되면 인덱스를 이용할 수 없다.

- 숫자타입은 반대부호를 붙여서 소팅에 이용할 수 있다(ref 471page)

- 또는 여러 쿼리로 나누어서 처리를 한다.

-- 두번째쿼리에 반복횟수가 작은 경우

-- 정렬갯수가 많아서 디스크를 이용할 경우 유용하다.


* 함수나 표현식을 이용한 정렬

- SELECT * FROM e ORDER BY emp_no+10 처럼 식은 인덱스 이용안됨


* ORDER BY를 튜닝하기 힘들때는 WHERE을 최적화해서 건수를 최대한 줄인다.




7.4.9 서브쿼리

- 가독성은 좋지만, 최적실행은 되지 않는다.


* Correlated subquery

 - 외부에서 정의된 테이블을 참조해서 검색을 수행

 - 독립적으로 실행되지 않고, 외부테이블 이후 순차실행


* Self-Contained subquery

 - 외부쿼리와 상관없이 항상 같은 값을 반환

 - 외부 쿼리보다 먼저 실행 => 외부 검색을 위한 상수로 사용됨이 일반적


* 서브쿼리의 제약 사항

 - LIMIT 절은 사용할 수 없다.

 - 서브쿼리를 이용해 한 테이블을 동시에 읽고/쓰기 할 수 없다.


* SELECT 절에 사용된 서브 쿼리

- 일반적으로 SELECT에 사용된 서브쿼리는 결과가 1개를 반환해야한다.


* FROM 절에 사용된 서브 쿼리

- FROM 절에 사용된 서브 쿼리는 항상 임시테이블을 사용, 비유율적일때가 많다.

- 서브쿼리가 반환하는 결과가 크거나, 대용량 칼럼이 있다면 디스크에 임시테이블을 만들고, 병목이 생긴다.

 




switch, if (java 1.6.0_30

language 2013.01.07 15:12 posted by dev.bistro
java version "1.6.0_30"
Java(TM) SE Runtime Environment (build 1.6.0_30-b12)
Java HotSpot(TM) 64-Bit Server VM (build 20.5-b03, mixed mode)
Compiled from "UseIf.java"
public class UseIf extends java.lang.Object{
public UseIf();
  Code:
   0:	aload_0
   1:	invokespecial	#1; //Method java/lang/Object."":()V
   4:	return

public static void main(java.lang.String[]);
  Code:
   0:	bipush	99
   2:	istore_1
   3:	ldc	#2; //String 
   5:	astore_2
   6:	iload_1
   7:	iconst_1
   8:	if_icmpne	17
   11:	ldc	#3; //String 1
   13:	astore_2
   14:	goto	58
   17:	iload_1
   18:	iconst_2
   19:	if_icmpne	28
   22:	ldc	#4; //String 2
   24:	astore_2
   25:	goto	58
   28:	iload_1
   29:	iconst_3
   30:	if_icmpne	39
   33:	ldc	#5; //String 3
   35:	astore_2
   36:	goto	58
   39:	iload_1
   40:	iconst_4
   41:	if_icmpne	50
   44:	ldc	#6; //String 4
   46:	astore_2
   47:	goto	58
   50:	iload_1
   51:	iconst_5
   52:	if_icmpne	58
   55:	ldc	#7; //String 5
   57:	astore_2
   58:	return

}


Compiled from "UseSwitch.java"
public class UseSwitch extends java.lang.Object{
public UseSwitch();
  Code:
   0:	aload_0
   1:	invokespecial	#1; //Method java/lang/Object."":()V
   4:	return

public static void main(java.lang.String[]);
  Code:
   0:	bipush	99
   2:	istore_1
   3:	ldc	#2; //String 
   5:	astore_2
   6:	iload_1
   7:	tableswitch{ //1 to 5
		1: 40;
		2: 46;
		3: 52;
		4: 58;
		5: 64;
		default: 70 }
   40:	ldc	#3; //String 1
   42:	astore_2
   43:	goto	70
   46:	ldc	#4; //String 2
   48:	astore_2
   49:	goto	70
   52:	ldc	#5; //String 3
   54:	astore_2
   55:	goto	70
   58:	ldc	#6; //String 4
   60:	astore_2
   61:	goto	70
   64:	ldc	#7; //String 5
   66:	astore_2
   67:	goto	70
   70:	return

}



'language' 카테고리의 다른 글

Groovy  (0) 2013.10.25
switch, if (java 1.6.0_30  (0) 2013.01.07

7.4.6. JOIN

RealMysql 2013.01.04 20:07 posted by dev.bistro


7.4.6 JOIN


* JOIN의 순서와 인덱스

인덱스 탐색(Index seek) => 인덱스 스캔(Index scan) => 최종 레코드 Read


(일반적으로 가장 먼저 읽히는 테이블을 '드라이빙 테이블'이라 하고 가끔은 아우터 테이블을 드라이빙 테이블이라 하기도 한다)


- 드라이빙 테이블을 읽을 때는 '인덱스 탐색'1번 -> 스캔만 계속 실행

- 드리븐 테이블은 '탐색', '스캔'을 레코드 건수만큼 반복한다.

-- 그래서 1:1로 조인되더라도 드리븐 테이블을 읽는것이 훨씬 부하가 크다.

-- 그래서 옵티마이저는 '드리븐 테이블'을 최적으로 읽을 수 있게 최적화한다.



* JOIN 칼럼의 데이터 타입

- JOIN 에서도 각 칼럼의 타입이 일치하지 않으면 인덱스가 효율적이지 않다.


* OUTER JOIN의 주의사항

 OUTER로 조인되는 테이블의 칼럼에 대한 조건은 모두 ON 절에 명시해야한다.


* INNER JOIN과 OUTER JOIN의 선택

- INNER : 조인의 양쪽 테이블에 모두 존재하는 경우만 반환

- OUTER : OUTER에 존재하면 무조건 반환한다.

- OUTER가 느리다는 편견은 버려라, 성능의 차이는 거의 없다. 중요한것은 업무rule에 따라 선택하는것.


* FULL OUTER JOIN 구현

- MySQL은 FULL OUTER JOIN을 제공하지 않는다, 단 UNION으로 효과를 비슷하게 구현할 수 있다.

- 두 테이블을 OUTER 조인을 연결해서 UNION 으로 더하면 된다.

- UNION은 중복제거를 하기 때문에, 각 OUTER JOIN에서 중복을 제거하고 UNION ALL을 하면 좀 더 빠르다.


* 조인 순서로 인한 쿼리 실패

- MySQL은 ANSI 표준으로 INNER JOIN, LEFT JOIN을 제공한다 ANSI 표준에서는 반드시 JOIN 키워드의 좌우측에 명시된 테이블의 칼럼만 ON 절에 사용가능

- A-B-C순서로 INNER JOIN을 할 경우는 순서에 맞춰서 A-B ==> A or B - C 순으로 JOIN 해야한다.


* JOIN과 FOREIGN KEY

- FOREIGN KEY와 JOIN은 아무런 연관이 없다. FK의 주 목적은 무결성을 보장하기 위해서이다.



* 지연된 조인(Delayed Join)

- 지연된 조인이란 조인이 실행되기 전 GroupBy/OrderBy를 처리하는 방식을 의미(Limit가 특히 큰 효과)

- 할수있는 모든 수행을 다하고 마지막에 join을 하면 JOIN 횟수를 줄일 수 있다.


***  페이징에 관한 이슈 457 Page 꼭 참고할것 , 지연된 조인!***





티스토리 툴바