쿼리테스트를 위한 테스트 데이터 1000만건을 insert을 해야한다. 이런 미션을 해결하기 위해 procedure를 사용했다.
여러 SQL문을 하나의 SQL문 처럼 정리하여 CALL procedure명
라는 명령어로 실행할 수 있게 만든 것을 저장프로시저(Stored Procedure)라고 한다.
저장프로시저는 MySQL버전 5.0이상에서 사용할 수 있다.
DELIMITER $$
DROP PROCEDURE IF EXISTS FILL_RATE_TEST_DATA$$
CREATE PROCEDURE myTEST()
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE j INT DEFAULT 1;
DECLARE log_date VARCHAR(255);
WHILE i <= 30 DO
SET log_date = DATE_FORMAT(DATE_SUB(NOW(), INTERVAL i DAY), '%Y%m%d');
WHILE j <= 30000 DO
INSERT INTO 테이블 (LOG_DATE, ID, REQ_CNT) VALUES (log_date, '0x2011', 3000000);
SET j = j + 1;
END WHILE;
SET j = 0;
END WHILE;
END$$
DELIMITER $$
CALL myTEST()
DELIMITER
는 저장프로시저에서 구분문자를세미콜론(;)
이 아닌 다른 문자로 변경해준다. 위의 예에서는$$
을 사용했다.
90만건을 insert를 하는 데 236s
을 기다려야한다.
다음으로 시도한 방버은 쿼리실행을 TRANSCATION
안에 넣는 것이다.
DELIMITER $$
DROP PROCEDURE IF EXISTS FILL_RATE_TEST_DATA$$
CREATE PROCEDURE myTEST()
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE j INT DEFAULT 1;
DECLARE log_date VARCHAR(255);
START TRANSACTION;
WHILE i <= 30 DO
SET log_date = DATE_FORMAT(DATE_SUB(NOW(), INTERVAL i DAY), '%Y%m%d');
WHILE j <= 30000 DO
INSERT INTO 테이블 (LOG_DATE, ID, REQ_CNT) VALUES (log_date, '0x2011', 3000000);
SET j = j + 1;
END WHILE;
SET j = 0;
END WHILE;
COMMIT;
END$$
DELIMITER $$
CALL myTEST()
START TRANSACTION
과 COMMIT;
사이에 쿼리문을 넣어주면 된다.
실행속도는 68s
거의 4배 빨라진 것을 알 수 있다.
Procedure에서 cursor와 trigger 등을 응용 사용하는 법이 있다.
다음 사이트를 참조하면 된다.
우선 Java의 String
객체는 immutable(불변의) 클래스이다. 그래서 한번 생성되면 수정이 불가능 하다.
다음은 String
객체의 특성을 나열 한다.
String을 만들때는 두가지 방식이 존재한다.
String a = "abc";
String b = new String("abc");
우선 차이를 설명하는 예를 보자
String a = "abc";
String b = "abc";
System.out.println(a == b); //True
System.out.println(a.equals(b)); //True
a
와 b
는 Method Area에서 같은 메모리를 참조 한다.
String c = new String("abc");
String d = new String("abc");
System.out.println(c == d); //False
System.out.println(c.equals(d)); //True
c
와 d
는 다른 heap영역에서 다른 object이다. 다른 object는 다른 메모리 참조한다.
String을 만들때 객체를 새로 만드는 것보다 ""
으로 String을 만드는 것이 불필요한 객체를 안만들어서 더 유용하다고 한다.
다음 예를 보자
public static void main(String[] args) {
String a = new String("abc");
changeText(a);
System.out.println(a);
}
public static void changeText(String a) {
a = "cd";
}
이 예제에서 print되는 것은 “abc”이다.
이러한 이유는 Java는 항상 pass by value
를 하기 때문이다. 즉 changeText()
메소드를 지나면서 a
에 저장되었던 “abc”는 무시되고 “cd”가 새롭게 heap생성이된다. 처음에 생성되었던 a는 여전히 “abc”를 참조하고 있다. 이는 앞서 설명한 Java에서는 String이 immutable한 클래스이기 때문이다. 즉 참조에 의한 값전달(passed by reference)는 지원하지 않는다.
immutable하지 않는 String을 만들고 싶으면 StringBuilder
를 사용하면 된다.
다음 예는 changeText()
메소드의 기능을 살리는 방식이다.
public static void main(String[] args) {
StringBuilder x = new StringBuilder("ab");
changeText(x);
System.out.println(x);
}
public static void changeText(StringBuilder x) {
x.delete(0, 2).append("cd");
}
여기서 StringBuilder는 값이 변할 수 있다. 그리고 새로운 객체를 생성하는 것이 아니라 새로운 값을 할당한다.
요약하면 Java는 값(변수?)의한 전달만 가능하다!! 참조를 통한 전달은 지원하지 않는다.
C++로 passed by reference
의 예를 보면 다음과 같다.
void change(string &x) {
x = "cd";
}
int main(){
string x = "ab";
change(x);
cout << x << endl;
}
최종적인 x는 “cd”가 출력된다. heap에 생성된 x의 메모리주소를 참조하여 값을 변경하였다.
curl
은 command line용 data transfer tool이다. download/upload 모두 가능하며 HTTP/HTTPS/FTP/LDAP/SCP/TELNET/SMTP/POP3
등 주요한 프로토콜을 지원하며 Linux/Unix 계열 및 Windows 등 주요한 OS 에서 구동되므로
여러 플랫폼과 OS에서 유용하게 사용할 수 있다. 또 libcurl 이라는 C 기반의 library 가 제공되므로 C/C++ 프로그램 개발시 위의 protocol 과 연계가 필요하다면 libcurl 을 사용하여 손쉽게 연계할 수 있다. 또 libcurl은 PHP, ruby, PERL 및 여러 언어에 바인딩되어 있으므로 사용하는 언어나 개발환경에 맞게 libcurl 을 사용할 수 있다.
Linux나 Mac OS X 에는 기본 탑재되어 있다.
sudo brew install curl
로 설치하면 된다.
curl [options...] <url>
형식으로 사용하면 된다.
option 처리는 GNU getopt를 사용하므로 하이픈(-)하나를 붙이는 short형식의 옵션과 하이픈두개(–)두개로 시작되는 long 형식의 options이 있다.
short | long | 설명 | 비고 |
---|---|---|---|
-v | –verbose | 동작하면서 자세한 옵션을 출력한다. | |
-s | –silent | 정숙 모드. 진행 내역이나 메시지등을 출력하지 않는다. -o 옵션으로 remote data 도 /dev/null 로 보내면 결과물도 출력되지 않는다 | HTTP response code 만 가져오거나 할 경우 유리 |
-o | –output FILE | curl 은 remote 에서 받아온 데이타를 기본적으로는 콘솔에 출력한다. -o 옵션 뒤에 FILE 을 적어주면 해당 FILE 로 저장한다. (download 시 유용) | |
-O | –remote-name | file 저장시 remote 의 file 이름으로 저장한다. -o 옵션보다 편리하다. | |
-l | –head | HTTP header 만 보여주고 content 는 표시하지 않는다 | |
-L | –location | 서버에서 HTTP 301 이나 HTTP 302 응답이 왔을 경우 redirection URL 로 따라간다. –max-redirs 뒤에 숫자로 redirection 을 몇 번 따라갈지 지정할 수 있다. 기본 값은 50이다 |
curl -v daum.net 을 실행하면 결과값으로 다음과 같이 HTTP 302 가 리턴된다. < HTTP/1.1 302 Object Moved Location: http://www.daum.net/ -L 옵션을 추가하면 www.daum.net 으로 재접속하여 결과를 받아오게 된다.</span> |
-k | –insecure | https 사이트를 SSL certificate 검증없이 연결한다. | wget 의 –no-check-certificate 과 비슷한 역할 수행 |
-J | –remote-header-name | 어떤 웹서비스는 파일 다운로드시 Content-Disposition Header 를 파싱해야 정확한 파일이름을 알 수 있을 경우가 있다. -J 옵션을 주면 헤더에 있는 파일 이름으로 저장한다. | curl 7.20 이상부터 추가된 옵션 |
-D | –dump-header <file> | <file> 에 HTTP header 를 기록한다. | |
-d | –data | HTTP Post data | FORM 을 POST 하는 HTTP나 JSON 으로 데이타를 주고받는 REST 기반의 웹서비스 디버깅시 유용한 옵션이다 |
curl http://www.gnu.org/software/bash/manual/html_node/index.html
curl -o index.html http://www.gnu.org/software/bash/manual/html_node/index.html
curl -O http://www.gnu.org/software/bash/manual/html_node/index.html
curl -O http://www.gnu.org/software/bash/manual/html_node/index.html -O http://www.gnu.org/savannah-checkouts/gnu/libiconv/documentation/libiconv-1.13/iconv.1.html
-C / --continue-at <offset>
옵션을 주면 이어받기 가능 (offset에 - 를 주면 전송이후 부분부터 이어받음)
curl -C - -O http://www.gnu.org/software/bash/manual/html_node/index.html
-z / --time-cond <time>
HTTP 헤더에 If-Modified-Since: 헤더를 추가하여 특정일 이후에 변경되었으면 다운로드 수행 아래 예제는 2011년 12월 21일 이후에 변경되었으면 다운로드 수행
curl -z 21-Dec-11 http://www.example.com/yy.html
날자앞에 - 를 추가하면 If-Unmodified-Since: 헤더를 추가하여 특정일 이전에 변경되었으면 다운로드 수행 아래 예제는 2011년 12월 21일 이전에 변경되었으면 다운로드함 (날자에 - 추가)
curl -z -21-Dec-11 http://www.example.com/yy.html
HTTP Header 나 contents 는 빼고 HTTP Response code 만 출력한다. 서버의 정상 작동 여부 점검때 유용하다.
curl -s -o /dev/null -w "%{http_code}\n" http://www.example.com/yy.html
id/pwd 가 필요한 사이트의 경우 -u(– user) 옵션 뒤에 userid:password 를 지정하여 인증할 수 있다
curl -v -u userid:password http://www.example.com/user.html
-i 옵션을 사용하면 서버의 응답에 서버가 보낸 HTTP 헤더를 추가하여 출력한다. 디버깅에 유용한다.
curl -i https://api.github.com -u valid_username:valid_password
-X POST 옵션을 추가하거나 -d( –data) 옵션을 지정하면 기본값으로 POST 로 설정됨
<form method="POST" action="post.php">
<input type=text name="first_name">
<input type=text name="last_name">
<input type=submit name=press value=" OK ">
</form>
POST 데이타는 “param1=value1¶m2=value2” 형식으로 전달
curl -d "first_name=Bruce&last_name=Wayne&press=%20OK%20" http://posttestserver.com/post.php
데이타에 공백이나 기타 특수 문자가 있을 경우 URL encoding 을 해야 한다. 공백일 경우 일일이 + 로 변환해서 전송해야 하지만 최신 버전의 curl(7.18.0 이후) 은 FORM 파라미터를 URL Encoding 해주는 –data-urlencode 옵션을 사용하면 별도로 인코딩을 해주지 않아도 된다.
curl --data-urlencode "first_name=Bruce" --data-urlencode "last_name=Wayne" --data-urlencode "press= OK " http://posttestserver.com/post.php
Hidden field 전송시 일반 필드처럼 name=value 형식으로 전송하면 된다.
file POST할 경우 file name 앞에 @ 를 붙여줌
curl -d @myPostfile http://posttestserver.com/post.php
curl 은 POST 시 데이타를 text 로 취급하므로 binary 데이타는 깨질 수 있다. 제대로 전송하려면 –data-binary 옵션을 추가해야 한다.
curl --data-binary @myBinary.jpg http://posttestserver.com/post.php
다음과 같은 파일 업로드 FORM이 있을 때
<form method="POST" enctype='multipart/form-data' action="upload.php">
<input type=file name=upload>
<input type=submit name=press value="OK">
</form>
localfilename은 upload 할 파일명, submit은 press=OK
curl --form upload=@localfilename --form press=OK http://localhost/upload.php
특정한 HTTP Header를 설정해서 보내야 할 경우(Ex: json data등) -H (–header) 옵션으로 헤더를 설정할 수 있다.
curl -d @myJson.js -H "Content-Type: application/json" http://localhost:8080/jsonEcho
특정 브라우저인(Browser) 것처럼 동작하기 위해서는 -A ( –user-agent) 옵션을 사용할 수 있다.
curl -d @myJson.js -H "Content-Type: application/json" --user-agent "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.14 (KHTML, like Gecko) Chrome/24.0.1292.0 Safari/537.14" http://localhost:8080/jsonEcho
curl -d @myJson.js -H "Content-Type: application/json" --user-agent "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)" http://localhost:8080/jsonEcho
curl -d @myJson.js -H "Content-Type: application/json" --user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0" http://localhost:8080/jsonEcho
Referer 를 체크하는 사이트일 경우 -e ( –referer) 옵션으로 Referer URL 을 설정할 수 있다.
curl --referer http://www.example.come/from http://www.example.com/to
아니면 -H 옵션으로 referer 헤더를 지정해도 된다.
curl -H "Referer: http://www.example.come/from" http://www.example.com/to
SSL의 후속 버전인 TLS의 버전을 지정할 수 있다. 지정하지 않을 경우 서버와 negotiation하여 결정한다.
curl --tlsv1.2 https://www.example.come
다음 옵션으로 사용할 SSL 의 버전을 지정할 수 있다. 지정하지 않을 경우 서버와 negotiation하여 결정한다. SSL 은 오래 됐으니 SSL 보다는 TLS 를 사용하는게 좋다.
curl --sslv3 https://www.example.come
GROUP_CONCAT
은 서로 다른 결과를 한줄로 합쳐서 보여줘야 할 경우 사용하는 MySQL 명령어이다.
이는 전체 결과를 서버로 들고와서 for문을 돌려 문자열을 붙여도 되지만 SELECT쿼리를 사용하여 합쳐져 있는 문자열을 받는게 더 편하다.
select * from test;
key | value |
---|---|
가구 | 편한가구 |
가구 | 싼 가구 |
가구 | 신혼집 가구 |
가구 | 신혼부부 가구 |
가구 | 신혼부부 가구 |
GROUP_CONCAT
을 사용하면 다음과 같다.SELECT key, GROUP_CONCAT(value) FROM test GROUP BY key;
key | value |
---|---|
가구 | 편한가구,싼 가구,신혼집 가구,신혼부부 가구, 신혼부부 가구 |
GROUP_CONCAT
의 기본적으로 문자열 사이에 쉼표(,)가 붙게 된다. 구분자를 변경하고 싶을 때에는 SEPARATOR '구분자'
를 함께 사용하면 된다.SELECT kye, GROUP_CONCAT(value SEPARATOR '/') FROM test GROUP BY key;
key | value |
---|---|
가구 | 편한가구/싼 가구/신혼집 가구/신혼부부 가구/ 신혼부부 가구 |
DISTINCT
를 사용한다.SELECT key, GROUP_CONCAT(DISTINCT value) FROM test GROUP BY key;
key | value |
---|---|
가구 | 편한가구,싼 가구,신혼집 가구,신혼부부 가구 |
order by
를 사용한다.SELECT key, GROUP_CONCAT(DISTINCT value ORDER BY valeu) FROM test GROUP BY key;
MySQL에서 group by 로 문자열을 합칠땐 group_concat 을 이용한다.
Name | Description | |
---|---|---|
AVG() | Return the average value of the argument | |
BIT_AND() | Return bitwise AND | |
BIT_OR() | Return bitwise OR | |
BIT_XOR() | Return bitwise XOR | |
COUNT() | Return a count of the number of rows returned | |
COUNT(DISTINCT) | Return the count of a number of different values | |
GROUP_CONCAT() | Return a concatenated string | |
MAX() | Return the maximum value | |
MIN() | Return the minimum value | |
STD() | Return the population standard deviation | |
STDDEV() | Return the population standard deviation | |
STDDEV_POP() | Return the population standard deviation | |
STDDEV_SAMP() | Return the sample standard deviation | |
SUM() | Return the sum | |
VAR_POP() | Return the population standard variance | |
VAR_SAMP() | Return the sample variance | |
VARIANCE() | Return the population standard variance |
표 : MySQL_Doc
테이블의 데이터를 삭제하는 DDL명령어 이다.
데이터를 삭제 방식은 talbe의 명세만 남기고 DROP 후 CREATE한다. 즉 데이터가 존재하던 공간마저 제거하기 위한 명령어이다.
이런 방식으로 테이블의 데이터를 삭제하기 때문에 수행 속도는 DELETE보다 빠르지만, 데이터 복구가 불가능하다는 제한사항이 존재한다.
또 auto_increment까지 초기화 시켜준다.(5.0.13버전부터) 즉 table의 옵션을 초기상태로 돌려준다.
삭제하다가 외부키와의 의존관계 때문에 삭제할 수 없다는 메시지가 나오면 다음과 같이하면 된다.
SET foreign_key_checks = 0;
truncate TABLE_NAME;
SET foreign_key_checks = 1;
0은 해제 1은 다시 설정을 의미한다.
테이블의 데이터를 삭제하기 위한 명령어이다. WHERE
절을 통해 조건을 부여 할 수 있다.
데이터 삭제 방식은 한줄씩 순차적으로 삭제한다.
데비안 계열 중 우분투 서버
여기서 접근하는 모든 디렉토리는 권한이 있어야함.
apt-get install nginx # Nginx
apt-get install uwsgi # uWSGI
apt-get install uwsgi-plugin-python # python과 uWSGI를 연결하는 플러그인
디폴트 파일로 설정하는 방법
vi /etc/nginx/sites-available/default
server {
listen 80; # 연결할 포트
server_name 0.0.0.0;
location / { try_files $uri @app; }
location @app {
include uwsgi_params;
uwsgi_pass unix:socket파일이 위치할 경로;
# ex) /home/server/uwsgi.sock
}
}
vi /etc/uwsgi/apps-available/uwsgi.ini
[uwsgi]
chdir = 프로젝트 경로
uid = 실행할계정
gid = 실행할계정
chmod-socket = 666
socket = socket파일이 위치할 경로
module = 모듈이름(실행할 파일 이름)
callable = 연결될 Flask 모듈이름
virtualenv = python 가상 환경 경로(virtualenv)
참고로 프로젝트 경로는 root를 포함하지 않는 것이 좋다 (권한 문제 때문에)
허용하는 파일로 등록하기위해 apps-enabled 디렉토리에 link함
ln -s /etc/uwsgi/apps-available/uwsgi.ini /etc/uwsgi/apps-enabled/
세팅 후 재시작을 한다.
sudo service nginx restart
sudo service uwsgi restart
설정한 uwsgi에 맞춰서 실행
uwsgi /etc/uwsgi/apps-available/uwsgi.ini &