Join
Inner Outer Join
Join : 두 테이블을 합쳐서 하나로 보여준다.
Union : 합집합이다. 갯수가 같아야 한다.
mysql> select name from stu union select name from prof;
+-----------+
| name |
+-----------+
| pobi |
| honux |
| happy |
| 구승모 |
| 박재성 |
+-----------+
크로스 조인 : 두 테이블의 카테시안 곱
// 전체
mysql> select * from stu cross join prof;
+----+-------+-----+-----+-----------+
| id | name | pid | pid | name |
+----+-------+-----+-----+-----------+
| 1 | pobi | 1 | 1 | 구승모 |
| 1 | pobi | 1 | 2 | 박재성 |
| 2 | honux | 2 | 1 | 구승모 |
| 2 | honux | 2 | 2 | 박재성 |
| 3 | happy | 1 | 1 | 구승모 |
| 3 | happy | 1 | 2 | 박재성 |
+----+-------+-----+-----+-----------+
// 지도교수만(의미있는데이터)
mysql> select * from stu s join prof p where s.pid = p.pid;
+----+-------+-----+-----+-----------+
| id | name | pid | pid | name |
+----+-------+-----+-----+-----------+
| 1 | pobi | 1 | 1 | 구승모 |
| 2 | honux | 2 | 2 | 박재성 |
| 3 | happy | 1 | 1 | 구승모 |
+----+-------+-----+-----+-----------+
// 멋지게 동등조인 = 을 조인 조건에 사용
mysql> select * from stu s join prof p on s.pid = p.pid where p.name='구승모';
+----+-------+-----+-----+-----------+
| id | name | pid | pid | name |
+----+-------+-----+-----+-----------+
| 1 | pobi | 1 | 1 | 구승모 |
| 3 | happy | 1 | 1 | 구승모 |
+----+-------+-----+-----+-----------+
// 세타조인, 조인조건이 =이 아닌 나머지들
- where s.pid = p.pid는 조인조건이므로 좋은쿼리가 아니다.
- join조건은 on뒤에 적는게 일반적이다.
join은 닫힌연산이기때문에 결과물에 계속 join을 할 수 있다. 자기자신끼리도 join이 가능하다.
Q. 1번 학생이 듣고 있는 수업과 담당 교수 이름을 표시해보세요.
mysql> select s.name, c.name, p.name from stu s join sugang g on s.id = g.uid join class c on g.cid = c.cid join prof p on c.pid = p.pid where id = 1;
+------+--------------------+-----------+
| name | name | name |
+------+--------------------+-----------+
| pobi | 게임제작개론 | 구승모 |
| pobi | 에자일방법론 | 박재성 |
+------+--------------------+-----------+
//이름구분
mysql> select s.name as 학생, c.name as 강의명, p.name as 지도교수 from stu s join sugang g on s.id = g.uid join class
+--------+--------------------+--------------+
| 학생 | 강의명 | 지도교수 |
+--------+--------------------+--------------+
| pobi | 게임제작개론 | 구승모 |
| pobi | 에자일방법론 | 박재성 |
+--------+--------------------+--------------+
Outer join
left join(outer join) : 왼쪽의 조건이 안맞더라도 보여줘라
mysql> select * from stu left join prof on stu.pid = prof.pid;
+----+-------+-----+------+-----------+
| id | name | pid | pid | name |
+----+-------+-----+------+-----------+
| 1 | pobi | 1 | 1 | 구승모 |
| 3 | happy | 1 | 1 | 구승모 |
| 2 | honux | 2 | 2 | 박재성 |
+----+-------+-----+------+-----------+
right join(outer join): 오른쪽 조건이 안맞더라도 보여줘라
mysql> select * from stu right join prof on stu.pid = prof.pid;
+------+-------+------+-----+-----------+
| id | name | pid | pid | name |
+------+-------+------+-----+-----------+
| 1 | pobi | 1 | 1 | 구승모 |
| 2 | honux | 2 | 2 | 박재성 |
| 3 | happy | 1 | 1 | 구승모 |
+------+-------+------+-----+-----------+
DB Index
인덱스 : 테이블에 대한 동작의 속도를 높여주는 자료구조 무조건 빠르게 해주는것이 아니라 하나의 성능을 개선하면 다른한쪽이 저하가 된다(Trade Off). Insert, Update, Delete속도를 희생해서 Read속도를 매우 높인다.
기본세팅
- load data를 통해 200만건의 레코드를 삽입한다.
SET foreign_key_checks=0;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` char(16) NOT NULL,
`name` varchar(16) DEFAULT NULL,
`last_visit` datetime DEFAULT NULL,
`money` decimal(10,0) DEFAULT NULL,
`choo` char(16) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `choo` (`choo`),
CONSTRAINT `user_ibfk_1` FOREIGN KEY (`choo`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOAD DATA LOCAL INFILE 'data.csv'
INTO TABLE user
FIELDS TERMINATED BY ','
IGNORE 1 LINES;
- set foreign_key_checks=0 데이터를 삽입할때 외래키를 고려하지 않는다.
- KEY
choo
(choo
), CONSTRAINTuser_ibfk_1
FOREIGN KEY (choo
) REFERENCESuser
(id
)를 할때 외래키 검사를 안하게 된다.
mysql -u jimmy -p jimmydb –local-infile=1 < index_ex.sql 명령어를 통해 index_ex.sql의 명령어를 실행하고 data.csv를 집어넣는다.
mysql> select @@foreign_key_checks;
+----------------------+
| @@foreign_key_checks |
+----------------------+
| 1 |
+----------------------+
1 row in set (0.00 sec)
mysql> set @@foreign_key_checks=0;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@foreign_key_checks;
+----------------------+
| @@foreign_key_checks |
+----------------------+
| 0 |
+----------------------+
- foreign_key_checks를 1에서 0으로 바꾼다.
실습
mysql> select count(id) from user;
+-----------+
| count(id) |
+-----------+
| 2000000 |
+-----------+
mysql> select count(*) from user where id like 'm%';
+----------+
| count(*) |
+----------+
| 83262 |
+----------+
1 row in set (0.03 sec)
mysql> select count(*) from user where money=1200;
+----------+
| count(*) |
+----------+
| 189 |
+----------+
1 row in set (0.53 sec)
- 0.03초만에 id가 m으로 시작되는것이 83262개이다. 굉장히 빨리 실행이됬다.
- 밑에꺼랑 위에꺼랑 시간이 굉장히 차이가 많이 난다. 왜??
쿼리마다 성능이 다른이유?
- 특정 칼럼에 대한 인덱스가 자동으로 만들어진다.
- primary key 인덱스 자동 생성
- foreign key에도 인덱스가 자동 생성된다.
mysql> show index from user;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| user | 0 | PRIMARY | 1 | id | A | 1820892 | NULL | NULL | | BTREE | | |
| user | 1 | choo | 1 | choo | A | 1781468 | NULL | NULL | YES | BTREE | | |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
// 예쁘게
mysql> show index from user\G;
*************************** 1. row ***************************
Table: user
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: id
Collation: A
Cardinality: 1867779
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
*************************** 2. row ***************************
Table: user
Non_unique: 1
Key_name: choo
Seq_in_index: 1
Column_name: choo
Collation: A
Cardinality: 1977604
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
2 rows in set (0.00 sec)
2 rows in set (0.00 sec)
- id, choo column에 BTREE타입의 인덱스가 존재를 한다.
- index는 show index명령어로 확인이 가능하다.
mysql> select count(*) from user where id like 'home%';
+----------+
| count(*) |
+----------+
| 5 |
+----------+
1 row in set (0.00 sec)
mysql> select count(*) from user where choo like 'home%';
+----------+
| count(*) |
+----------+
| 5 |
+----------+
1 row in set (0.00 sec)
- id와 choo에는 index가 걸려있기때문에 검색하는데 굉장히 빨리걸린다.
mysql> select count(*) from user where money = 6600;
+----------+
| count(*) |
+----------+
| 195 |
+----------+
1 row in set (0.55 sec)
mysql> select count(*) from user where money = 1;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.47 sec)
- money에는 index가 없기때문에 인덱스가 있는 Column에 비해서 오래걸린다.
어떻게 속도를 빨리할까?? 인덱스를 만든다.
mysql> create index idx_user1 on user(money);
- idx_user1이라는 이름을 가진 인덱스를 user(money)에 만든다.
mysql> select count(*) from user where money = 1000;
+----------+
| count(*) |
+----------+
| 194 |
+----------+
1 row in set (0.00 sec)
mysql> select * from user where money=1000;
194 rows in set (0.01 sec)
- index가 만들어지면 이전과 비해서 굉장히 검색이 빨라진다.
create index indexName on TableName(ColumnName);을 이용하면 인덱스를 만들수 있다.
- 모든열에 인덱스를 만들면 되지 않은가?? 안된다 왜?? 인덱스를 만들때마다. insert update delete가 느려지고 용량이 굉장히 커진다.
Written on August 24, 2018