'MySQL'에 해당되는 글 24건
- 2009/09/22
- 2009/05/29
- 2009/05/13
- 2009/03/25
- 2009/01/09
- 2008/12/29
- 2008/12/26
- 2008/12/22
- 2008/12/22
- 2008/11/25
|
[mysqld] # generic configuration options |
|
mysql> # 아버지 테이블 : 유니크한 키값을 갖는다. mysql> # 나쁜 아들 테이블 : 테이블 생성이 되지 않는다. |
| mysql> show variables like '%date%'; +------------------------------+--------------+ | Variable_name | Value | +------------------------------+--------------+ | date_format | %Y-%m-%d | | datetime_format | %Y%m%d%H%i%s | | log_slave_updates | OFF | | low_priority_updates | OFF | | query_cache_wlock_invalidate | OFF | | sql_log_update | ON | | sql_low_priority_updates | OFF | | sql_safe_updates | OFF | +------------------------------+--------------+ 8 rows in set (0.02 sec) |
|
mysql> SET GLOBAL datetime_format ='%Y%m%d%H%i%s'; mysql> SHOW VARIABLES LIKE 'datetime_format'; |
그 동안 알고는 있었지만 정작 써먹지 않았던,
문자열 함수 몇개를 적고 넘어갈까 한다.
다년간에 걸친 니코틴과 카페인 섭취로 인하여 뇌기능이 비약적으로 떨어진 것을
메모를 통해 강제 각인 시키고자 한다 할까? (-_-);;
# 아래는 MySQL 한글 레펀런스의 문자열 함수 페이지를 링크해 둔 것이다.
<<Link :MySQL 한글 레퍼런스 - 스트링함수>>
# 함수 설명
1. LEFT, RIGHT
이눔의 함수들은 문자열의 오른쪽, 왼쪽을 끊어 오는 기능을 한다.
<<기억 안 났을 때>>
이걸 기억 못해서,
맨날 LEFT는 SUBSTRING 함수를 써서 일일이 끊어 왔고,
RIGHT는 LENGTH함수를 써서 그만큼 SUBSTRING으로 끊어오거나, REVERSE를 사용해서 비교했었다..
(ㅠ,.ㅠ)
<<사용방법>>
LEFT(문자열, 끊어올 문자 개수)
RIGHT(문자열, 끊어올 문자 개수)
<<실행화면>>
|
mysql> SELECT LEFT('1234567890', 5); mysql> SELECT RIGHT('1234567890', 5); |
|
mysql> SELECT SUBSTRING_INDEX('12345674890', '4',1); mysql> SELECT SUBSTRING_INDEX('12345674890', '4',2); |
|
mysql> SELECT TRIM(BOTH '0' FROM '0001200034000' ); mysql> SELECT TRIM(LEADING'0' FROM '0001200034000' ); mysql> SELECT TRIM(TRAILING '0' FROM '0001200034000' ); |
메모만 해두고 블로그에 적는 것을 까먹고 있었던 내용을 간만에 적어본다.
혹시 테이블 생성할 때, INT 에 괄호치고 값을 넣어 본 기억이 있는가?
아니면, 왜 이거 INT(8)이야? 하면서 테이블 생성자에게 화를 내본적이 있는가?
그렇다면....... 당신은 바보~ -0-/
헉...!!! ..... 내가 말을 잘 못했소... 돌던지지 말아주시오~~
(*,.ㅜ);;
자... 간단히 테스트를 해보자.
<< 예제 >>
##################################################################################################
# 1. 테스트 테이블 생성
CREATE TABLE int_test (
int_1 INT(1),
int_1_z INT(1) ZEROFILL,
int_5 INT(5),
int_5_z INT(5) ZEROFILL,
int_9 INT(9),
int_9_z INT(9) ZEROFILL,
int_11 INT(11),
int_11_z INT(11) ZEROFILL
)ENGINE=INNODB DEFAULT CHAR SET =UTF8;
# ---------------------------------------------------------------------------
# 2. 테스트 값 넣어보기
INSERT INTO int_test VALUES(1,1,1,1,1,1,1,1);
INSERT INTO int_test VALUES(12345,12345,12345,12345,12345,12345,12345,12345);
INSERT INTO int_test VALUES(1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890,1234567890);
##################################################################################################
당신의 평소 생각대로라면,
# ------------------------------
SELECT *
FROM int_test;
# ------------------------------
의 결과는?
<< 수행 결과 >>
| mysql> SELECT * FROM int_test; +------------+------------+------------+------------+------------+------------+------------+-------------+ | int_1 | int_1_z | int_5 | int_5_z | int_9 | int_9_z | int_11 | int_11_z | +------------+------------+------------+------------+------------+------------+------------+-------------+ | 1 | 1 | 1 | 00001 | 1 | 000000001 | 1 | 00000000001 | | 12345 | 12345 | 12345 | 12345 | 12345 | 000012345 | 12345 | 00000012345 | | 1234567890 | 1234567890 | 1234567890 | 1234567890 | 1234567890 | 1234567890 | 1234567890 | 01234567890 | +------------+------------+------------+------------+------------+------------+------------+-------------+ 3 rows in set (0.00 sec) |
|
SQL> INSERT INTO number_test VALUES(12,12); 1 개의 행이 만들어졌습니다. SQL> INSERT INTO number_test VALUES(12345,12345);
NUMBER_2 NUMBER_5 |
쿼리를 날리다 보면, 필요에 따라 그룹별로 순위를 매겨야 할 때가 있다.
이에 대해 오라클에서는 그러한 기능을 제공하는데,
아래가 바로 그 예이다.
[Oracle]
SELECT empno, ename, job, sal,
ROW_NUMBER() OVER(PARTITION BY job ORDER BY sal) AS rnum
FROM scott.emp;
<<결과>>
|
EMPNO ENAME JOB SAL RNUM 14 개의 행이 선택되었습니다. |
| +-------+--------+-----------+------+------+ | empno | ename | job | sal | rnum | +-------+--------+-----------+------+------+ | 7902 | FORD | ANALYST | 3000 | 1 | | 7788 | SCOTT | ANALYST | 3000 | 2 | | 7369 | SMITH | CLERK | 800 | 1 | | 7900 | JAMES | CLERK | 950 | 2 | | 7876 | ADAMS | CLERK | 1100 | 3 | | 7934 | MILLER | CLERK | 1300 | 4 | | 7782 | CLARK | MANAGER | 2450 | 1 | | 7698 | BLAKE | MANAGER | 2850 | 2 | | 7566 | JONES | MANAGER | 2975 | 3 | | 7839 | KING | PRESIDENT | 5000 | 1 | | 7654 | MARTIN | SALESMAN | 1250 | 1 | | 7521 | WARD | SALESMAN | 1250 | 2 | | 7844 | TURNER | SALESMAN | 1500 | 3 | | 7499 | ALLEN | SALESMAN | 1600 | 4 | +-------+--------+-----------+------+------+ 14 rows in set (0.00 sec) |
| +----------------+----------------+----------+---------------+ | @val1:=@val1+1 | @val2:=@val1+1 | @val2:=0 | @val1=@val2+1 | +----------------+----------------+----------+---------------+ | 1 | 2 | 0 | 1 | +----------------+----------------+----------+---------------+ 1 row in set (0.00 sec) |
| (7902,'FORD','ANALYST',3000), |
| (7788,'SCOTT','ANALYST',3000), |
| (7369,'SMITH','CLERK',800), |
| (7900,'JAMES','CLERK',950), |
| (7876,'ADAMS','CLERK',1100), |
| (7934,'MILLER','CLERK',1300), |
| (7782,'CLARK','MANAGER',2450), |
| (7698,'BLAKE','MANAGER',2850), |
| (7566,'JONES','MANAGER',2975), |
| (7839,'KING','PRESIDENT',5000), |
| (7654,'MARTIN','SALESMAN',1250), |
| (7521,'WARD','SALESMAN',1250), |
| (7844,'TURNER','SALESMAN',1500), |
| (7499,'ALLEN','SALESMAN',1600); |
[스포일러]
결론부터 말하자면...
MyISAM, InnoDB, BDB, MEMORY 엔진을 사용할 경우,
NULL도 INDEX를 탄다 !!!
아래는 그 테스트와 MySQL 리퍼런스 링크에 관련된 내용이다.
[문제 제기]
요즘 나의 궁금중 중 하나가, 'MySQL에서 NULL 값이 인덱스를 탈까?' 라는 것이었다.
참고로,
오라클의 경우에는 NULL 일 경우 인덱스를 타지 않고,
그로 인해 NULL일 경우를 검색해야 한다면, FULL SCAN을 해야 한다고 알고 있다.
그래서인지 주위에서는 억지로 인덱스를 태우기 위해
DEFAULT '' 를 속성의 기본값으로 사용하는 경우를 볼 수 있었다.
흠... 평소에도 쓸데 없이 NULL을 사용하지 않고 ''를 사용하던 것에 불만이었던 나...
게다가 얼마 전에 읽었던,
The Top 20 Design Tips For MySQL Enterprise Data Architects 라는 짧은 PPT에서는
'필요 없는 경우에 굳이 NOT NULL 을 쓰는 것은 안 좋은 경우' 라고 얘기했기에,
'그럼 한 번 NULL이 인덱스를 타느냐 안 타느냐를 가지고 테스트 해보자'
라는 생각을 하게 되었다.
[테스트]
1. 테이블 준비 및 값 넣기
1.1. 임시 테이블 생성
-- ---------------------------------------------------------------
CREATE TABLE `nulltest` (
`id` int(11) NOT NULL auto_increment,
`col1` varchar(50) default NULL,
`col2` varchar(50) default NULL,
PRIMARY KEY(`id`),
KEY `nulltest_cols` (`col1`, `col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
-- ---------------------------------------------------------------
1.2. 임시 테이블에 널 값의 교차적인 값 입력
(아래 프로시저는 주석을 모두 제거해야 컴파일 됩니다. ^^;;)
-- ---------------------------------------------------------------
CREATE PROCEDURE `p_nulltest`()
BEGIN
DECLARE number INT DEFAULT 0; -- 반복 회수를 위한 변수
SET @number = 1; -- 1로 초기화
WHILE @number < 100000 DO -- 100000번 수행
INSERT INTO nulltest (col1,col2) VALUES (
-- 2로 나누어질 경우 NULL, 그렇지 않을 경우 랜덤숫자를 생성하여 입력
(CASE mod(@number,2) WHEN 0 THEN NULL ELSE CASE(ROUND(RAND()*10000) AS CHAR) END),
-- 3로 나누어질 경우 NULL, 그렇지 않을 경우 랜덤숫자를 생성하여 입력
(CASE MOD(@number,3) WHEN 0 THEN NULL ELSE CAST(ROUND(RAND()*10000) AS CHAR) END) );
SET @number = @number+1; -- 변수 1증가
END WHILE;
END
-- ---------------------------------------------------------------
1.3. 테스트 수행
1.3.1. col1 이 NULL인 경우 인덱스를 타는가?
EXPLAIN SELECT id FROM nulltest WHERE col1 IS NULL;
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | nulltest | ref | nulltest_cols | nulltest_cols | 153 | const | 50278 | Using where; Using index |
=> 인덱스를 탄다.
1.3.2. col1, col2 가 NULL인 경우 인덱스를 타는가?
EXPLAIN SELECT id FROM nulltest WHERE col1 IS NULL AND col2 IS NULL;
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | nulltest | ref | nulltest_cols | nulltest_cols | 306 | const,const | 13298 | Using where; Using index |
=> 역시 인덱스를 탄다.
1.4. 분석
위의 실행계획들을 보면, 둘다 인덱스를 이용하는 것을 볼 수 있으며,
이로 인해 NULL값도 인덱스에 들어갈 수 있다는 것을 알 수 있다.
[참고 문서]
나.. 웬지 괜히 테스트 한 듯...
MySQL 외국 리퍼런스를 보면.. (난 영어 능력이 딸려서, 한글만 검색하는뎅 ㅠ,.ㅠ)
http://dev.mysql.com/doc/refman/5.0/en/create-index.html
In MySQL 5.0 :
* 오직 MyISAM, InnoDB, BDB, MEMORY 에서만 인덱스에 NULL을 더 할 수 있다.
* 오직 MyISAM, InnoDB, BDB 에서는 BLOB, TEXT를 INDEX로 사용할 수 있다.
(사족이지만 이것도 좋은 정보)
라고 나온다....
으흐흑~ ㅠ.ㅠ
이넘의 저질 영어 울렁병... 언제나 고칠런지....
담부턴... 영어 리퍼런스도 항상 같이 보도록 노력하자..